1. 单例模式的定义
1.1 ES6单例模式
保证一个类 仅有一个 实例,并提供一个访问它的全局访问点。
class Window {
static getInstance(name) {
if (!this.instance) {
this.instance = new Window();
}
return this.instance;
}
}
var w1 = Window.getInstance();
var w2 = Window.getInstance();
console.log(w1 === w2); // true
1.2 ES5单例模式
let Window = function() { }
Window.getInstance = (function () {
let window = null;
return function () {
if (!window)
window=new Window();
return window;
}
})();
let window = Window.getInstance();
问题:并不能阻止客户端直接
new Window。
1.3 透明单例
let Window = (function () {
let window;
let Window = function () {
if (window) {
return window;
} else {
return (window = this);
}
}
return Window;
})();
let window1 = new Window();
let window2 = new Window();
console.log(window1 === window2) //true
问题:违反了单一职责原则。
1.4 单例与构建分离
function Window() { }
let createSingle = (function () {
let instance;
return function () {
if (!instance) {
instance = new Window();
}
return instance;
}
})();
let window1 = createSingle();
let window2 = createSingle();
console.log(window1 === window2);// true
1.5 通用的惰性单例
function Window() { }
var createSingle = function (Constructor) {
let instance;
const singleConstructor = function () {
if (!instance) {
instance = new Constructor(...arguments)
}
return instance;
}
return singleConstructor;
};
let CreateWindow = createSingle(Window);
let window1 = new CreateWindow();
let window2 = new CreateWindow();
console.log(window1 === window2);// true
1.6 命名空间
const MyApp = {};
MyApp.namespace = function (name, fn) {
const parts = name.split('.'), last = parts.pop();
let current = MyApp;
for (const i in parts) {
if (!current[parts[i]]) {
current[parts[i]] = {};
}
current = current[parts[i]];
}
current[last] = fn;
};
MyApp.namespace('event', () => console.log('event'));
MyApp.namespace('dom.style', () => console.log('dom.style'));
console.dir(MyApp);
// 上述代码等价于:
/* const MyApp = {
event: () => console.log('event'),
dom: {
style: () => console.log('dom.style')
}
}; */
2. 场景
2.1 登录浮窗
const createLoginLayer = (function () {
let div;
return function () {
if (!div) {
div = document.createElement('div');
div.innerHTML = '我是登录浮窗';
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
}
})();
document.getElementById('loginBtn').onclick = function () {
const loginLayer = createLoginLayer();
loginLayer.style.display = 'block';
};
2.2 redux
发布订阅、工厂模式、单例模式。
function createStore(reducer) {
let state;
let listeners = [];
function getState() {
return state;
}
function dispatch(action) {
state = reducer(state, action);
listeners.forEach(l => l());
}
function subscribe(listener) {
listeners.push(listener);
return () => {
listeners = listeners.filter(item => item != listener);
console.log(listeners);
}
}
dispatch({});
return {
getState,
dispatch,
subscribe
}
}
2.3 缓存
let express = require('express');
let fs = require('fs');
let cache = {};
let app = express();
app.get('/user/:id', function (req, res) {
let id = req.params.id;
let user = cache[id];
if (user) {
res.json(user);
} else {
fs.readFile(`./users/${id}.json`, 'utf8', function (err, data) {
let user = JSON.parse(data);
cache[id] = user;
res.json(user);
});
}
});
app.get('/user', function (req, res) {
let user = req.query;
fs.writeFile(`./users/${user.id}.json`, JSON.stringify(user), (err) => {
console.log(err);
res.json({ code: 0, data: '写入成功' });
});
});
app.listen(3000);