JS代理实现单例模式

JS设计模式之单例模式

单例模式--保证一个类仅有一个单例

1. 简单单例模式

// 简单单例模式
const Singleton = function (name) {
  this.name = name;
};
Singleton.instance = null;
Singleton.getInstance = function (name) {
  if (!Singleton.instance) {
    Singleton.instance = new Singleton(name);
  }
  return Singleton.instance;
};

const s1 = Singleton.getInstance("xiaxiang");
const s2 = Singleton.getInstance();

console.log(s1, s2, s1 === s2);

这种方式相对简单, 缺点是使用者必须知道这个类有获取单例方法


2. 透明单例方法

让使用者像平常一样, new出来的对象永远都是相同的一个

// 透明单例模式
function Singleton(name) {
  let instance = Singleton.instance;
  if (!instance) {
    Singleton.instance = {};
    instance = Singleton.instance;
  }
  instance.name = name;
  return instance;
}

const single1 = new Singleton("xiaxiang");
const single2 = new Singleton("xiaowai");

console.log(single1, single2, single2 === single1);
// true

其实 new 出来的对象就是该方法返回的对象, 以往返回默认的是 this, 现在显式返回方法静态属性, 从而实现单例效果.

该方法让单例化透明, 同时也让这个类无法扩展, 只能是单例, 若日后有更改需求, 十分麻烦, 这时候可以采用代理模式


3. 完美代理模式

function Singleton(name) {
  this.name = name;
}

const SingletonProxy = new Proxy(Singleton, {
  construct(target, args) {
    if (!SingletonProxy.instance) {
      SingletonProxy.instance = new Singleton(args);
      return SingletonProxy.instance;
    } else {
      return SingletonProxy.instance;
    }
  },
});

const single1 = new SingletonProxy("xia");
const single2 = new SingletonProxy("xiao");
console.log(single1, single2, single1 === single2);

优点

  1. 将定义类与使用类解耦, 对原有类没有产生任何影响
  2. 实现了懒加载, 只有当第一次使用单例代理时才会创建单例对象

4. 补充

const namespace1 = {
  get a() {
    return 1;
  },
  set a(value) {
    a = value;
  },
};

console.log((namespace1.a = 2));

使用 get set 方法控制对象属性的访问设置

单例模式可以使用类也可以直接使用对象, 具体视情况而定

posted @ 2021-03-21 16:26  随遇丿而安  阅读(265)  评论(0)    收藏  举报