amandakelake/blog

单例模式

amandakelake opened this issue · 2 comments

定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点

特性

系统中被唯一使用
一个类只有一个实例

实例

  • 登录框
  • 购物车
  • redux、vuex中的store

特别说明

单例模式没有private属性(java的特性)
ES6没有,TS除外
只能用Java代码来演示

用JS模拟java的单例

class SingleObject {
  login() {
    console.log("login")
  }
}

// 通过给类挂载一个静态方法,而且是自执行方法
// 通过闭包,返回唯一的实例instance
// 实例只有一个
SingleObject.getInstance = (function() {
  let instance;
  // 返回一个函数
  return function() {
    if (!instance) {
      instance = new SingleObject();
    }
    return instance
  }
})()

let obj1 = SingleObject.getInstance();
let obj2 = SingleObject.getInstance();

obj1.login();
obj2.login();

// 这里会返回true,说明是唯一的同一个实例
console.log('obj1 === obj2', obj1 === obj2);


// 但是,这里只能口头约定不能直接new SingleObject()
// 就算new了,也不会报错,下面会返回false
let obj3 = new SingleObject()
console.log('obj1 === obj3', obj1 === obj2);

jquery模拟了单例的**,只有一个$

if (window.jQuery != null) {
	return window.jQuery
} else {
	// 初始化
}

存在的问题

1,违反了单一职责原则
2、每次都会创建新的实例(可以做成惰性)

惰性单例

// 职责单一,不干涉fn的逻辑
const getSingle = function(fn) {
  // 闭包大兄弟,用来保存fn函数执行后的计算结果
  let result;
  return function() {
    return result || (result = fn.apply(this, arguments));
  }
}

// 模拟一个fn 生成一个iframe/div/script
const createIframe = function() {
  const iframe = document.createElement('iframe');
  document.body.appendChild(iframe);
  return iframe;
}

// 结合使用  创建唯一实例对象
const singleIframe = getSingle(createIframe);
ycai2 commented

代码对的 不过单例在英文中正确的叫法是Singleton哦

@ycai2 好的哈 感谢大兄弟