美文网首页
JavaScript 设计模式(中)——1.单例模式

JavaScript 设计模式(中)——1.单例模式

作者: Haleng | 来源:发表于2019-12-21 11:11 被阅读0次

1 单例模式

单例模式的定义是: 保证一个类仅有一个实例,并提供一个访问它的全局访问点;

1.1 实现单例模式

用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象;

var Singleton = function( name ){
  this.name = name;
  this.instance = null;
};
Singleton.prototype.getName = function(){
  alert ( this.name );
};
Singleton.getInstance = function( name ){
  if ( !this.instance ){
    this.instance = new Singleton( name );
  }
  return this.instance;
};
var a = Singleton.getInstance( 'sven1' );
var b = Singleton.getInstance( 'sven2' );
alert ( a === b ); // true

1.2 透明的单例模式

实现一个“透明”的单例类,用户从这个类中创建对象的时候,可以像使用其他任何普通类一样。

var CreateDiv = (function(){
  var instance;
  var CreateDiv = function( html ){
    if ( instance ){
      return instance;
    }
    this.html = html;
    this.init();
    return instance = this;
  };
  CreateDiv.prototype.init = function(){
    var div = document.createElement( 'div' );
    div.innerHTML = this.html;
    document.body.appendChild( div );
  };
  return CreateDiv;
})();
var a = new CreateDiv( 'sven1' );
var b = new CreateDiv( 'sven2' );
alert ( a === b ); // true

在这段代码中, CreateDiv 的构造函数实际上负责了两件事情。第一是创建对象和执行初始化 init 方法,第二是保证只有一个对象。虽然目前还没有接触过“单一职责原则”的概念,但可以明确的是,这是一种不好的做法,至少这个构造函数看起来很奇怪。

1.3 用代理实现单例模式(也是缓存代理的应用)

var CreateDiv = function( html ){
  this.html = html;
  this.init();
};
CreateDiv.prototype.init = function(){
  var div = document.createElement( 'div' );
  div.innerHTML = this.html;
  document.body.appendChild( div );
};
// 引入代理类 proxySingletonCreateDiv:
var ProxySingletonCreateDiv = (function(){
  var instance;
  return function( html ){
    if ( !instance ){
      instance = new CreateDiv( html );
    }
    return instance;
  }
})();
var a = new ProxySingletonCreateDiv( 'sven1' );
var b = new ProxySingletonCreateDiv( 'sven2' );
alert ( a === b );

1.4 JavaScript 中的单例模式

前几种单例模式的实现是接近传统面向对象语言中的实现,单例对象是从“类”中创建而来。如在 Java 中,如果需要某个对象,就必须先定义一个类,对象总是从类中创建而来的;而JavaScript 其实是一门无类( class-free)语言,因此,生搬单例模式的概念并无意义,JavaScript中只需要创建一个唯一的对象即可;

JavaScript 开发中经常会把全局变量当成单例来使用, 但全局变量存在很多问题,很容易造成命名空间污染,因而需要尽量减少全局变量使用:

  1. 适当使用命名空间,以对象字面量的方式:
var namespace1 = {
  a: function(){
    alert (1);
  },
};
  1. 使用闭包封装私有变量:
var user = (function(){
  var name = 'sven', age = 29;
  return {
    getUserInfo: function(){
      return name + '-' + age;
    }
  }
})();

1.5 惰性单例

惰性单例指的是在需要的时候才创建对象实例;

实例:创建登录浮窗,实现单例模式,并且在点击的时候才创建

var createLoginLayer = (function(){
  var div;
  return function(){
    if ( !div ){
      div = document.createElement( 'div' );
      div.innerHTML = '我是登录浮窗';
      div.style.display = 'none';
      document.body.appendChild( div );
    }
    return div;
  }
})();
document.getElementById( 'loginBtn' ).onclick = function(){
  var loginLayer = createLoginLayer();
  loginLayer.style.display = 'block';
};

1.6 通用的惰性单例

上部分代码违反单一职责原则的,创建对象和管理单例的逻辑都放在 createLoginLayer 对象内部,下次需要创建页面中唯一的 iframe ,或者 script 标签,就得把 createLoginLayer 函数几乎照抄一遍;因而考虑把不变的部分隔离出,即为管理单例的逻辑,用一个变量来标志是否创建过对象,若是则在下次直接返回这个已经创建好的对象,再把如何管理单例的逻辑从原来的代码中抽离出来,这些逻辑被封装在 getSingle 函数内部,创建对象的方法 fn 被当成参数动态传入 getSingle 函数:

var getSingle = function( fn ){
  var result;
  return function(){
    return result || ( result = fn .apply(this, arguments ) );
  }
};
var createLoginLayer = function(){
  var div = document.createElement( 'div' );
  div.innerHTML = '登录浮窗';
  div.style.display = 'none';
  document.body.appendChild( div );
  return div;
};
var createSingleLoginLayer = getSingle( createLoginLayer );
document.getElementById( 'loginBtn' ).onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = 'block';
};

1.7 单例模式小结

单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个。更奇妙的是,创建对象和管理单例的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威力;

系列链接

  1. JavaScript 设计模式(上)——基础知识
  2. JavaScript 设计模式(中)——1.单例模式
  3. JavaScript 设计模式(中)——2.策略模式
  4. JavaScript 设计模式(中)——3.代理模式
  5. JavaScript 设计模式(中)——4.迭代器模式
  6. JavaScript 设计模式(中)——5.发布订阅模式
  7. JavaScript 设计模式(中)——6.命令模式
  8. JavaScript 设计模式(中)——7.组合模式
  9. JavaScript 设计模式(中)——8.模板方法模式
  10. JavaScript 设计模式(中)——9.享元模式
  11. JavaScript 设计模式(中)——10.职责链模式
  12. JavaScript 设计模式(中)——11. 中介者模式
  13. JavaScript 设计模式(中)——12. 装饰者模式
  14. JavaScript 设计模式(中)——13.状态模式
  15. JavaScript 设计模式(中)——14.适配器模式
  16. JavaScript 设计模式(下)——设计原则
  17. JavaScript 设计模式练习代码

本文主要参考了《JavaScript设计模式和开发实践》一书

相关文章

  • JavaScript 设计模式(上)——基础知识

    系列链接 JavaScript 设计模式(上)——基础知识 JavaScript 设计模式(中)——1.单例模式 ...

  • Node.js与单例模式

    1、前端的JavaScript单例模式 单例模式是非常常用的设计模式,前端的JavaScript中单例模式代码可能...

  • JavaScript设计模式二(单例模式)

    JavaScript设计模式二(单例模式) 这边文章主要是JavaScript中的单例模式定义: 保证一个类仅有一...

  • python中OOP的单例

    目录 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 单例

    目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 前端开发工程师必备系列-几个简单的JS单例模式

    前端开发工程师必备系列-几个简单的JS单例模式 JavaScript单例模式 1. 单例模式 单例模式(Singl...

  • 单例模式

    1. 单例模式 在面向对象的程序设计中, 单例模式是最简单的设计模式,这种类型的设计模式属于创建型模型,所谓单例....

  • Java四种单例设计模式

    Java中的四种单例模式 单例模式是最容易理解的设计模式之一,介绍Java中单例模式的四种写法。 1.基本单例模式...

  • 设计模式 - 单例模式

    设计模式 - 单例模式 什么是单例模式 单例模式属于创建型模式,是设计模式中比较简单的模式。在单例模式中,单一的类...

  • JavaScript 设计模式(中)——1.单例模式

    1 单例模式 单例模式的定义是: 保证一个类仅有一个实例,并提供一个访问它的全局访问点; 1.1 实现单例模式 用...

网友评论

      本文标题:JavaScript 设计模式(中)——1.单例模式

      本文链接:https://www.haomeiwen.com/subject/fzownctx.html