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 相关文章推荐
DB.ASP 用Javascript写ASP很灵活很好用很easy
Jul 31 Javascript
jquery 操作DOM案例代码分享
Apr 05 Javascript
Javascript学习笔记之 函数篇(二) : this 的工作机制
Jun 24 Javascript
JS+DIV实现鼠标划过切换层效果的方法
May 25 Javascript
jqueryMobile使用示例分享
Jan 12 Javascript
同步异步动态引入js文件的几种方法总结
Sep 23 Javascript
微信小程序 本地存储及登录页面处理实例详解
Jan 11 Javascript
javascript 面向对象实战思想分享
Sep 07 Javascript
vue学习教程之带你一步步详细解析vue-cli
Dec 26 Javascript
360doc网站不登录就无法复制内容的解决方法
Jan 27 Javascript
Vue组件内部实现一个双向数据绑定的实例代码
Apr 04 Javascript
JavaScript中常用的3种弹出提示框(alert、confirm、prompt)
Nov 10 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截取汉字乱码问题解决方法mb_substr函数的应用
2008/03/30 PHP
php输入流php://input使用浅析
2014/09/02 PHP
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
2018/08/21 PHP
asp 取文本框名称代码
2008/12/02 Javascript
javascript 静态对象和构造函数的使用和公私问题
2010/03/02 Javascript
js 一个关于图片onload加载的事
2013/11/10 Javascript
jQuery选择器用法实例详解
2015/12/17 Javascript
js实现页面跳转的几种方法小结
2016/05/16 Javascript
jquery中用函数来设置css样式
2016/12/22 Javascript
JavaScrpt的面向对象全面解析
2017/05/09 Javascript
详解React开发中使用require.ensure()按需加载ES6组件
2017/05/12 Javascript
详解React-Native全球化多语言切换工具库react-native-i18n
2017/11/03 Javascript
JS遍历DOM文档树的方法实例详解
2018/04/03 Javascript
vue2.0 中使用transition实现动画效果使用心得
2018/08/13 Javascript
es6函数之尾调用优化实例分析
2020/04/25 Javascript
pyenv命令管理多个Python版本
2017/03/26 Python
python with提前退出遇到的坑与解决方案
2018/01/05 Python
Django中的Signal代码详解
2018/02/05 Python
使用Django启动命令行及执行脚本的方法
2018/05/29 Python
caffe binaryproto 与 npy相互转换的实例讲解
2018/07/09 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
2018/07/16 Python
如何用Python做一个微信机器人自动拉群
2019/07/03 Python
Python操作Sonqube API获取检测结果并打印过程解析
2019/11/27 Python
jupyter notebook 调用环境中的Keras或者pytorch教程
2020/04/14 Python
python 代码实现k-means聚类分析的思路(不使用现成聚类库)
2020/06/01 Python
详解python中的lambda与sorted函数
2020/09/04 Python
Python3.9.1中使用match方法详解
2021/02/08 Python
在html5的Canvas上绘制椭圆的几种方法总结
2013/01/07 HTML / CSS
2014年学习委员工作总结
2014/11/14 职场文书
2015年七一建党节慰问信
2015/03/23 职场文书
高中数学课堂教学反思
2016/02/18 职场文书
基于MySql验证的vsftpd虚拟用户
2021/11/07 MySQL
Nginx内网单机反向代理的实现
2021/11/07 Servers
Ruby序列化和持久化存储 Marshal和Pstore介绍
2022/04/18 Ruby
Oracle中日期的使用方法实例
2022/07/07 Oracle