旧的实现方式,通过必包和立即执行函数表达式。
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, 如果
已经存在,旧不会在创建新实例。