JS 设计模式单例模式

旧的实现方式,通过必包和立即执行函数表达式。

var UserStore = (function(){
  var _data = [];

  function add(item){
    _data.push(item);
  }

  function get(id){
    return _data.find((d) => {
        return d.id === id;
    });
  }

  return {
    add: add,
    get: get
  };
}());

UserStore 被赋了一个立即执行函数的运行结果: 这个函数执行并返回了一个对象,通过对象暴露了两个函数方法。
同时避免了对数据 _data 的直接访问。

缺点:不能达到单例模式所要求的良好的 immutability 。其他代码可能会修改暴露的函数方法,活着是重写 UserStore 。

利用模块实现单例模式

利用 ES 6 新特性

  • 第一种: 对象字面量的形式

    const _data = [];

    const UserStore = {
    add: item => _data.push(item),
    get: id => _data.find(d => d.id === id)
    }

    Object.freeze(UserStore);
    export default UserStore;

优点: 可读性;
良好的 immutability: 因为 UserStore 是用 const 声明的, 所以其他代码不会重写和破坏它;
使用 Object.freeze() 方法保护 UserStore 的方法也不能被改变,同时不能给 UserStore 添加新的属性和方法;
良好的代码跟踪: 因为使用了 ES 6 模块导出语法, 可以明确在代码中饮用模块的位置

  • 第二种: class 语法

    class UserStore {
    constructor(){
    this._data = [];
    }

    add(item){
    this._data.push(item);
    }

    get(id){
    return this._data.find(d => d.id === id);
    }
    }

    const instance = new UserStore();
    Object.freeze(instance);

    export default instance;

对象字面量的 immutability 和 non-overridability

对象字面量是可以复制的,即使是 const 声明的, 也可以通过使用 Object.assign() 方法。

  • 第三种:

    class UserStore {
    constructor(){
    if(! UserStore.instance){
    this._data = [];
    UserStore.instance = this;
    }

    return UserStore.instance;
    }

    //rest is the same code as preceding example

    }

    const instance = new UserStore();
    Object.freeze(instance);

    export default instance;

确保单例模式不被其他代码破坏, 同时满足面向对象语言特性

利用引用 instance 类的实例,可以检查是否代码中已经初始化过一个 UserStore, 如果
已经存在,旧不会在创建新实例。

https://www.sitepoint.com/whats-so-bad-about-the-singleton/

你可能感兴趣的:(web,设计模式,javascript)