了解js中设计模式吗?动手实现一下单例模式?

618 阅读2分钟

核心思想:

限制类实例化次数只能一次,一个类只有一个实例,并提供一个访问它的全局访问点。

至于单例模式的优缺点什么的在这里咱就不过多的去说了,来看看实现方式吧,理解了之后,大家自然就知道该把单例模式用在什么地方了

实现方式:

使用一个变量存储类实例对象(值初始为 null/undefined )。进行类实例化时,判断类实例对象是否存在,存在则返回该实例,不存在则创建类实例后返回。多次调用类生成实例方法,返回同一个实例对象。

看代码:

let CreateSingle = (function(){
     let instance;//开关
     return function(name){
         if(instance){//判断实例是否已经存在
             return instance;
         }
         this.name = name;//类的业务逻辑
         return instance = this;//实例化之后关闭开关,不允许再次实例化
     }
 })();

let lili = new CreateSingle('lili');
let wuyou = new CreateSingle('wuyou');

console.log(wuyou);// lili

首先用一个自执行函数来创建了一个闭包环境,这样的话我们可以有一个开关来判断这个实例是不是已经存在了,并且还不会污染全局变量。

首先用开关来判断 类是否已经实例化,如果已经实例化过了,那么直接关闭开关,不允许再次实例化就可以了

比如:

let lili = new CreateSingle('lili');
let wuyou = new CreateSingle('wuyou');

console.log(wuyou);// lili

可以看到虽然实例化了两次,但是后面这一次实例化得到的对象还是之前第一次实例化的对象,所以得到的名字还是 lili

这样我们就实现单例模式了。

不过上面的这个写法有点乱,控制函数和我们实际的类混在一起了,把它们分开的话可能会更好,我们可以这样写:

let CreateSingle = (function(){
  let instance;
  return function(name){
    if(instance){
      return instance;
    }
    return instance = new Single(name);
  }
})();

let Single = function(name){
  this.name = name;
}

let lili = new CreateSingle('lili');
let wuyou = new CreateSingle('wuyou');

console.log(wuyou);// lili

下面的 Single 是我们实际的类,用来写我们的业务逻辑,上面的 CreateSingle 才是控制单例的函数,经过它的包装之后,我们的Single就只能被实例化一次了

let lili = new CreateSingle('lili');
let wuyou = new CreateSingle('wuyou');

console.log(wuyou);// lili

这时候我们的业务逻辑就可以分开来写,不会受到影响

来个小案例:

let CreateSingle = function(fn){
  let instance;
  return function(name){
    return instance || (instance = new fn(name));
  }
};

let Single = function(text){
  let msg = document.createElement('div');
  msg.innerHTML = text;
  msg.style.display = 'none';
  document.body.appendChild(msg);
  return msg;
}

let msgBox = CreateSingle(Single);
document.onclick = function(){
  let msgEl = msgBox('这里是弹窗的内容');
  msgEl.style.display = 'block';
}

这样写的话呢,控制函数和类也充分解耦了,类的方法也可以随意拓展