JavaScript设计模式中单例模式的使用方法

Posted 三水草肃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计模式中单例模式的使用方法相关的知识,希望对你有一定的参考价值。

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

使用场景:

  1. 有一些对象往往只需要一个,就可以使用,比如线程池、全局缓存、浏览器中的 window 对象等;登录框浮窗会多次使用,登录浮窗就适合用单例模式

实现单例模式:

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

  1. 单例模式的模版

const Singleton = function (name) 
  this.name = name;
  this.instance = null;
;

Singleton.prototype.getName = function () 
  console.log(this.name);
;

Singleton.getInstance = function (name, type) 
  if (!this.instance) 
    this.instance = new Singleton(name);
  
  return this.instance;
;

const a = Singleton.getInstance("a");
const b = Singleton.getInstance("b");
console.log(Singleton.getInstance()); // name: 'a', ...
console.log(a === b); // true
console.log(a.name); // a
console.log(b.name); // a
  1. 创建唯一的 div 节点

/**
 * 1. 创建对象和执行初始化init方法
 * 2. 保证只有一个对象
 *
 * 如果要创建千千万万的div。要让这个类从单例变成一个普通的可产生多个实例的类,那我们必须要改造CreateDom构造函数,把控制唯一那一段去掉。可以使用代理实现单例模式
 */

const CreateDom = (function () 
  let instance;
  const Create = function (html) 
    if (instance) 
      return instance;
    
    this.html = html;
    this.init();
    return (instance = this);
  ;
  Create.prototype.init = function () 
    const div = document.createElement("div");
    div.innerHTML = this.html;
    document.body.appendChild(div);
  ;
  return Create;
)();

const a = new CreateDom("a");
const b = new CreateDom("b");
console.log(a === b); // true
  1. 使用代理实现单例模式

    通过引入代理类的方式,把负责管理单例的逻辑移到了代理类 ProxySingleCreateDiv 中。这样一来,CreateDiv 就变成了一个普通的类,需要跟 ProxySingleCreateDiv 组合起来可以达到单例模式的效果
// 代理实现单例模式;
const CreateDiv = function (html) 
  this.html = html;
  this.init();
;
CreateDiv.prototype.init = function () 
  const div = document.createElement("div");
  div.innerHTML = this.html;
  document.body.appendChild(div);
;

// 引入代理类
const ProxySingleCreateDiv = (function () 
  let instance;
  return function (html) 
    if (!instance) 
      return new CreateDiv(html);
    
    return instance;
  ;
)();
const a1 = new ProxySingleCreateDiv("a1");
const b1 = new ProxySingleCreateDiv("b1");
console.log(a1 === b1); // false

惰性单例:

创建实例对象和管理单例的职责分别放置在两个方法里,这两个独立变化而互不影响,当它们连在一起的时候,就完成了创建唯一实例对象的功能。

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

  1. 符合单一职责原则

    1. 例子:
    const getSingle = function (fn) 
      let result;
      return function () 
        return result || (result = fn.apply(this, arguments));
      ;
    ;
    
    const creataLoginLayer = function () 
      const div = document.createElement("div");
      div.innerHTML = this.html;
      div.style.display = "none";
      document.body.appendChild(div);
      return div;
    ;
    
    const creataSingleLoginLayer = getSingle(creataLoginLayer);
    
    1. 也可以创建 iframe…
    2. 如果要给列表绑定 click 事件,如果是通过 ajax 动态往列表里追加数据,在使用事件代理的前提下,click 事件实际上只需要在第一次渲染列表的时候被绑定一次,可以使用 getSingle 函数
    const btnEvent = getSingle(function () 
      document.getElementById("div1").onclick = function () 
        console.log("div1");
      ;
      return true;
    );
    const render = function () 
      console.log("开始渲染");
      btnEvent();
    ;
    render();
    render();
    render();
    

    render和btnEvent分别执行了3次,但是div只绑定了一次事件

以上是关于JavaScript设计模式中单例模式的使用方法的主要内容,如果未能解决你的问题,请参考以下文章

Javascript:最佳单例模式

单例模式进阶之Android中单例模式的应用场景

Python中单例设计模式

python中单例模式的实现-通过闭包函数和魔术方法__new__实现单例模式

Java中单例模式和静态类的区别

java中单例设计模式