4. 设计模式之单例模式

单例模式(Singleton),保证一个类只有一个实例,并提供一个访问它的全局访问点。

一说到只有一个实例,并能全局访问,我觉着前端同学能想到的类库就太多太多了,在前几年我们还没有像现在这样实行模块化开发的时候,我们用到的JQuerymomentlodash等等类库,全部都能满足上面的特点。

但其实我们在平时的应用当中,大多数情况下只能感受到单个实例的好处,也没太多感受到单个实例的坏处。但是我们可以举一个很通俗的例子,我们平时都会通过玩游戏来消遣时间,在Dota中有这么一个道具叫「刷新球」,它的作用是重置所有物品和技能的冷却时间,那如果我玩一个英雄,他的某个技能很厉害,那我是不是出6个「刷新球」,爆炸了...但其实很破坏游戏体验,所以Dota中有一个机制就是不管出多少个刷新球,他们共享一个冷却CD,那怎么实现这样的效果呢?

单例模式就可以闪亮登场了:

// 刷新球类
class Refresher {
    constructor() {
        this.cooldown = 180;
        this.lastCD = 0;
        this.timer = null;
      	this.instance=null;
    }
  
  	// static 静态方法调用直接在类上进行,不能在类的实例上调用。静态方法通常用于创建实用程序函数。
  	static getInstance() {
      	if(!this.instance) {
          this.instance = new Refresher();
        }
      	return this.instance;
    }

    use() {
        if (this.lastCD) {
            console.log('技能还没冷却好!');
            return;
        }

        this.lastCD = this.cooldown;
        this.timer = setInterval(() => {
            this.lastCD--;
            if (!this.lastCD) {
                clearInterval(this.timer);
            }
        }, 1000);
    }

    getCD() {
        return this.lastCD;
    }
}

var refresher = Refresher.getInstance();
var refresher2 = Refresher.getInstance();

refresher.use();

refresher.getCD(); // 174
refresher2.getCD(); // 174

refresher.use(); // 技能还没冷却好!
refresher2.use(); // 技能还没冷却好!

由上可见「单例模式」的作用。在日常工作中,单例模式的使用多被状态管理工具替代了。假如没有状态管理工具,我们也可以借助「单例模式」来实现购物车功能


参考

大话设计模式 -- 程杰
从ES6重新认识JavaScript设计模式(一): 单例模式