JavaScript设计模式---单例模式详解【四种基本形式】


Posted in Javascript onMay 16, 2020

本文实例讲述了JavaScript设计模式---单例模式.分享给大家供大家参考,具体如下:

单例模式也称为单体模式,其中:

1,单体模式用于创建命名空间,将系列关联的属性和方法组织成一个逻辑单元,减少全局变量。
 逻辑单元中的代码通过单一的变量进行访问。

2,三个特点:
 ① 该类只有一个实例;
 ② 该类自行创建该实例,即在该类内部创建自身的实例对象;
 ③ 向整个系统公开这个实例接口

3,单体模式有四种基本形式:

第一种,最简单的单体,只被实例化一次    我简记为json对象

(1)基本结构

var userInfo={//已经自行被实例化 其实是一json对象
    name:"测试名称",
    dept:"测试PD",
    code:"测试PD001",
    getName:function () {
      return "测试"
    }
  };

(2)使用方法与json的使用方法一致:使用点 " . "的方式访问

alert(userInfo.getName())

单体模式用来划分命名空间,并将一群相关的属性和方法组织到一起的简单介绍:

var comm={};//一个空对象
  comm.userInfo={//空对象下的第一个命名空间
    name:"命名空间1下的",
    code:"001"
  }

  comm.funcInfo={//空对象下的第二个命名空间
    funcName:"命名空间2下的",
    code:"002"
  }

总结:该种方式可以看出对象的变量值不是动态加载的,而且对象没有显示初始化,由此有了第二种单体模式。

第二种,具有局部变量的单体

要求:模拟一个使用ajax从数据库加载数据的过程

 (1)简单模拟一下ajax过程

//模拟一个Ajax操作
  function Ajax() {};//空对象
  //静态函数 模拟作为从数据库取值 此处值写死的
  Ajax.request=function (url,fn) {
    //默认永远回调成功
    if(true){
      fn("测试值1","测试值2")
    }
  }

(2)在最简单的单体中出现了数据不是动态从数据库加载的,而且没有显示实例化对象,此处使用闭包原理解决上述问题

//使用闭包的原理解决:动态从数据库加载数据 ,显示实例化
  var userInfo=(function () {
    //(1)利用闭包使单体有自己的私有局部变量
    var name="";
    var code="";
    //(2)利用ajax访问数据库取到数据
    Ajax.request("url",function (n,c) {//由于模拟的ajax中只是简单传递参数,所以第一个参数可以任意
         name=n;
         code=c;
    })
    //(3)单体实现私有变量的赋值
    return {
      name:name,
      code:code
    }
  })()

(3)使用该种方式的单体,不用实例化 可以直接返回一个单体 【因为使用userInfo时,直接return一个单体回来】

alert(userInfo.name);

总结:

(1)优点,灵活

(2)弊端:return 单体数据量比较大时,都需要从数据库取数据,每次加载都要执行,会影响程序性能。由于该种方式每次加载都要直接执行,return单体数据量大时会影响呈现的性能,于是有了第三种单体模式。

第三种,惰性单体 提供的解决方案为:调方法时才实例化单体,而不是加载时就执行。

于是在第二种的基础上进行修改为,

(1)模拟ajax从数据库加载数据不变

//模拟一个Ajax操作
  function Ajax() {}
  //静态函数 模拟作为从数据库取值
  Ajax.request=function (url,fn) {
    //默认永远回调成功
    if(true){
      fn("测试值1","测试值2")
    }
  }

(2)动态从数据库加载数据 ,显示实例化,使用一个函数(Init())封装产生单体的函数,通过一个私有变量来返回函数(Init())

//使用闭包的原理解决:动态从数据库加载数据 ,显示实例化
  var UserInfo=(function () {

    var userInfo="";//私有变量

    function Init() {//在产生单体方式为包裹一层初始化函数
      //利用闭包使单体有自己的私有局部变量
      var name="";
      var code="";
      //利用ajax访问数据库取到数据
      Ajax.request("url",function (n,c) {
        name=n;
        code=c;
      })
      //单体
      return {
        name:name,
        code:code,
      }
    }

    return {//此时开始调用初始化函数实现单体的产生
      getInstance:function () {
        if(userInfo){//userInfo=""为false
          return userInfo;
        }else {
          userInfo=Init();
          return userInfo;
        }
      }
    }

  })()

(3)使用   访问UserInfo对象里面的获取初始化获取对象的函数(getInstance())

alert(UserInfo.getInstance().name);

总结:使用惰性单体实质上是通过对产生单体的函数进行再一次封装(使用函数封装),再在通过该类提供的唯一接口(getInstance()方法)访问初始化单体 的函数。

第四种,分支单体

简单的用处:做Ajax的时候根据不同的浏览器获得不同的XHR。(将浏览器之间的差异封装到动态方法,适用于解决浏览器之间的差异。)

比如下面一个简单的例子:在电脑不同分辨率的情况下初始化不一样的界面。(这里只是弹窗显示而已)

(1)获取电脑的分辨率

//得到机器的分辨率
  var screenWidth=window.screen.width;//width
  var screenHeight=window.screen.height;//height

(2)进行分支判断处理 ,将差异封装到动态方法中

var portalInfo=(function () {
    //单体
   var $1280_1024={info:'1,2,3,5'}//单体1
   var $1366_768={info:'4,2,1,2'}//单体2     //动态图选择浏览器的差异结果(这里是分辨率)
     if(screenWidth==1280){
       return $1280_1024;//返回单体进行初始化
     }else if(screenWidth==1366){
       return $1366_768;//返回单体进行初始化
     }else {
       throw new Error("请检查你当前的电脑分辨率")
     }
   })();

(3)使用 ,获取最终的结果

alert(portalInfo.info)//我的结果为4,2,1,2 这是由于我的电脑的分辨率为1366*768

总结一下,对于分支单体有一个缺点:分支中,单体1和单体2都被创建了,并保存在内存中了,但只用到一个。需要在 计算时间 和 占用内存 两者中取舍。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScript之引用类型介绍
Aug 10 Javascript
Jquery动态改变图片IMG的src地址示例
Jun 25 Javascript
JQuery控制div外点击隐藏而div内点击不会隐藏的方法
Jan 13 Javascript
jQuery选择器用法实例详解
Dec 17 Javascript
剖析Node.js异步编程中的回调与代码设计模式
Feb 16 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
Mar 22 Javascript
js实现悬浮窗效果(支持拖动)
Mar 09 Javascript
Angularjs cookie 操作实例详解
Sep 27 Javascript
js 两个日期比较相差多少天的实例
Oct 19 Javascript
Vue头像处理方案小结
Jul 26 Javascript
小程序中设置缓存过期的实现方法
Jan 14 Javascript
vue中echarts引入中国地图的案例
Jul 28 Javascript
JavaScript接口实现方法实例分析
May 16 #Javascript
JavaScript 类的封装操作示例详解
May 16 #Javascript
jquery+css3实现的经典弹出层效果示例
May 16 #jQuery
js抽奖转盘实现方法分析
May 16 #Javascript
JSONP 的原理、理解 与 实例分析
May 16 #Javascript
JavaScript随机数的组合问题案例分析
May 16 #Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
May 18 #Javascript
You might like
php实现中文转数字
2016/02/18 PHP
php 判断字符串编码是utf-8 或gb2312实例
2016/11/01 PHP
Smarty缓存机制实例详解【三种缓存方式】
2019/07/20 PHP
return false,对阻止事件默认动作的一些测试代码
2010/11/17 Javascript
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
jquery使用ajax实现微信自动回复插件
2014/04/28 Javascript
简化版手机端照片预览组件
2015/04/13 Javascript
JavaScript和JQuery的鼠标mouse事件冒泡处理
2015/06/19 Javascript
JavaScript中日常收集常见的10种错误(推荐)
2017/01/08 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(1)
2017/02/20 Javascript
详解nodejs微信公众号开发——1.接入微信公众号
2017/04/10 NodeJs
Angular.js 4.x中表单Template-Driven Forms详解
2017/04/25 Javascript
Angular2中select用法之设置默认值与事件详解
2017/05/07 Javascript
深入理解Commonjs规范及Node模块实现
2017/05/17 Javascript
Vue项目引发的「过滤器」使用教程
2019/03/12 Javascript
React组件设计模式之组合组件应用实例分析
2020/04/29 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
2020/09/21 Javascript
jQuery实现tab栏切换效果
2020/12/22 jQuery
使用cx_freeze把python打包exe示例
2014/01/24 Python
python装饰器初探(推荐)
2016/07/21 Python
使用pyecharts无法import Bar的解决方案
2020/04/23 Python
Python字符编码与函数的基本使用方法
2017/09/30 Python
Python opencv实现人眼/人脸识别以及实时打码处理
2019/04/29 Python
python Matplotlib底图中鼠标滑过显示隐藏内容的实例代码
2019/07/31 Python
python函数参数(必须参数、可变参数、关键字参数)
2019/08/16 Python
python修改FTP服务器上的文件名
2019/09/11 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
Python 爬取淘宝商品信息栏目的实现
2021/02/06 Python
西班牙购买隐形眼镜、眼镜和太阳镜网站:Lentiamo.es
2020/06/11 全球购物
中科方德软件测试面试题
2016/04/21 面试题
JPA的特点
2014/10/25 面试题
我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
2014/03/30 面试题
财务出纳员岗位职责
2013/11/26 职场文书
2014大学校园光棍节活动策划书
2014/09/29 职场文书
写给汽车4S店的创业计划书,拿来即用!
2019/08/09 职场文书
2019个人工作自我评价范文(3篇)
2019/09/19 职场文书