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只绑定了一次事件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值