单体单例模式:一个构造函数,无所使用多少次 new
,值都是相等的。
function Person() {
this.name = "John";
}
function Singleton(construct) {
let obj = new construct();
Singleton = function () {
return obj;
}
return obj;
}
let p1 = new Singleton(Person); // 这里用不用 new 的可以
let p2 = new Singleton(Person);
console.log(p1 === p2);
观察者模式两点
Observer
的 fn
方法Observer
的 name
属性Subject
的 state
属性Subject
的 observers
属性Subject
的 setState
,listen
,unlisten
方法class Observer {
constructor(name, fn = () => {}) {
this.name = name;
this.fn = fn;
}
};
class Subject {
constructor(state) {
this.state = state;
this.observers = [];
}
setState(newState) {
if(this.state === newState) return;
this.state = newState;
this.observers.map(item => item.fn(newState));
}
listen(observer) {
if (this.observers.indexOf(observer) === -1) {
this.observers.push(observer);
}
}
unlisten(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
};
const p1 = new Observer('小夫', (state) => {console.log(`${state} ==> 小夫--> 打篮球`)});
const p2 = new Observer('胖虎', (state) => {console.log(`${state} ==> 胖虎--> 睡大觉`)});
const s1 = new Subject('学习');
s1.listen(p1);
s1.listen(p2);
console.log(s1);
s1.setState('玩');
s1.unlisten(p1);
s1.setState('学习');
发布订阅有点像观察者模式,但是有不尽相同。发布订阅模式很常见,就是 addEventListener
class Subscribe {
constructor() {
this.events = {};
}
includeEvent(event) {
return this.events[event] !== undefined;
}
notIncludesEvent(event) {
return this.events[event] === undefined;
}
on(event, func) {
if (this.notIncludesEvent(event)) {
this.events[event] = [func];
} else {
this.events[event].push(func);
}
}
off(event, func) {
if (this.includeEvent(event)) {
const index = this.events[event].indexOf(func);
if (index !== -1) {
this.events[event].splice(index, 1);
}
}
}
trigger(event) {
if (this.includeEvent(event)) {
this.events[event].map(item => item());
}
}
}
let sub = new Subscribe();
function func1() {console.log('func1');}
function func2() {console.log('func2');}
function func3() {console.log('func3');}
function func4() {console.log('func4');}
function func5() {console.log('func5');}
sub.on('click', func1);
sub.on('click', func2);
sub.on('click', func3);
sub.on('click', func4);
sub.on('click', func5);
sub.trigger('click');
sub.off('click', func3);
sub.off('click', func5);
sub.trigger('click');
一个问题匹配多个解决方案,不一定要用到哪一个。而且有可能随时增加多个方案。
常见的就是购物车,各种活动,满减,满折,红包等等。
需要暴露借口,后期可以添加与删除,而不影响源代码。
function caculatePrice() {
let sales = {
"100-10": (price) => price -= 10,
"200-25": (price) => price -= 25,
"80%": (price) => price *= 0.8
};
function calculate(type, price) {
if (!sales[type]) return "没有这个折扣";
return sales[type](price);
}
calculate.add = (type, func) => {
sales[type] = func;
}
calculate.del = (type) => {
delete sales[type];
}
return calculate;
}
const calculate = caculatePrice();
const res = calculate('100-10', 300);
console.log(res);
const res2 = calculate('80%', 300);
console.log(res2);
const res3 = calculate('70%', 300);
console.log(res3);
calculate.add("70%", (price) => price *= 0.7);
const res4 = calculate('70%', 300);
console.log(res4);
calculate.del("80%");
const res5 = calculate('80%', 300);
console.log(res5);