# 设计模式
# 责任链模式
const pipe =
(f1, f2) =>
(...args) =>
f1.call(null, f2.apply(null, args));
const compose = (...fns) => fns.reduce(pipe, fns.shift());
const request = (params) => {
console.log('模拟请求开始, 参数是', params, ' 3秒后返回结果');
return new Promise((resolve) => {
setTimeout(() => {
resolve({ text: '请求成功' });
}, 3000);
});
};
const log = (next) => (params) => {
console.log('请求开始与:', new Date().toString());
return next(params);
};
const authorization = (next) => async (params) => {
const { auth, ...otherParams } = params;
if (auth) {
const code = await getAuthCode();
console.log('获取验证码:', code);
return next({ code, ...otherParams });
}
return next(params);
};
const getAuthCode = () => {
return new Promise((resolve) => {
console.log('模拟获取, 3秒后返回code');
setTimeout(() => {
resolve(1234);
}, 3000);
});
};
const requestDispatch = compose(log, authorization)(request);
(async () => {
const res = await requestDispatch({ auth: true });
console.log('获取请求结果:', res);
})();
# 有限状态机(FSM)
/**
* 售货机有三种状态:待机、选择糖果和出售糖果,并且有两种操作:插入硬币和转动手柄。
* 当顾客插入硬币时,如果硬币数不足,则售货机不会发生任何操作;如果硬币数足够,则会进入选择糖果状态。
* 在选择糖果状态下,顾客可以选择想要的糖果,并转动手柄。如果糖果库存不足,则售货机不会出售糖果并返回硬币;
* 如果库存充足,则售货机出售糖果并返回剩余硬币。
*/
const vendingMachine = {
standby: {
insertCoin: (coins) => {
if (coins >= 10) {
return { nextState: 'selectCandy', coins: coins - 10 };
} else {
return { coins };
}
},
},
selectCandy: {
insertCoin: (coins) => {
return { coins: coins + 5 };
},
turnHandle: (candyCount, coins) => {
if (candyCount <= 0) {
return { nextState: 'standby', coins };
} else if (coins < 5) {
return { coins };
} else {
return {
nextState: 'sold',
candyCount: candyCount - 1,
coins: coins - 5,
};
}
},
},
sold: {
insertCoin: (coins) => {
return { coins };
},
turnHandle: () => {
return {};
},
},
};
执行
/**
* 售货机有三种状态:standby、selectCandy和sold,分别对应待机状态、选择糖果状态和出售糖果状态。
* 每个状态都有两个可能的操作:插入硬币和转动手柄。
* 每个操作都是一个函数,它接受当前状态的硬币数、糖果库存数作为参数,并返回一个对象,
* 该对象指示状态机的下一个状态、输出以及硬币和糖果库存的更新。
*/
let coins = 0;
let candyCount = 5;
let currentState = 'standby';
console.log(`当前状态:${currentState},当前硬币数:${coins},当前糖果数:${candyCount}`);
// 插入10元硬币
const { nextState, coins: updatedCoins } = vendingMachine[currentState].insertCoin(coins + 10);
currentState = nextState;
coins = updatedCoins;
console.log(`当前状态:${currentState},当前硬币数:${coins},当前糖果数:${candyCount}`);
# IOC & DI
class A {
name: string
constructor(name: string) {
this.name = name
}
}
class C {
name: string
constructor(name: string) {
this.name = name
}
}
//中间件用于解耦
class Container {
modeuls: any
constructor() {
this.modeuls = {}
}
provide(key: string, modeuls: any) {
this.modeuls[key] = modeuls
}
get(key) {
return this.modeuls[key]
}
}
const mo = new Container()
mo.provide('a', new A('nameA'))
mo.provide('c', new C('nameB'))
class B {
a: any
c: any
constructor(container: Container) {
this.a = container.get('a')
this.c = container.get('c')
}
}
new B(mo)
# 观察者模式
- 多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
- 目标对象和观察者对象逻辑互不干扰, 但是没法对观察者做过滤
- 符合依赖倒置原则
let observer_ids = 0
let observed_ids = 0
// 观察者类
class Observer {
constructor(name) {
this.id = name || observer_ids++
}
// 观测到变化后的处理
update(ob) {
console.log('观察者' + this.id + `-检测到被观察者${ob.id}变化`)
}
}
// 被观察者列
class Observed {
constructor() {
this.observers = []
this.id = observed_ids++
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer)
}
// 删除观察者
removeObserver(observer) {
this.observers = this.observers.filter(o => o.id !== observer.id)
}
// 通知所有的观察者
notify() {
this.observers.forEach(observer => {
observer.update(this)
})
}
}
const mObserved = new Observed()
const mObserver1 = new Observer()
const mObserver2 = new Observer()
mObserved.addObserver(mObserver1)
mObserved.addObserver(mObserver2)
mObserved.notify()
- 把上面观察者和被观察者这两个类作为基类供其他类实现
class Teacher extends Observer {
constructor (name) {
super()
this.name = name
}
update(st) {
// super.update(st);
console.log(st.name + `提交了${this.name}作业`)
}
}
class Student extends Observed {
constructor (name) {
super()
this.name = name
}
submitHomeWork() {
this.notify(this)
}
}
const teacher1 = new Teacher('数学')
const teacher2 = new Teacher('语文')
const stu1 = new Student('小玲')
const stu2 = new Student('小明')
const stu3 = new Student('小李')
stu1.addObserver(teacher1)
stu1.addObserver(teacher2)
stu2.addObserver(teacher1)
stu2.addObserver(teacher2)
stu3.addObserver(teacher1)
stu3.addObserver(teacher2)
stu1.submitHomeWork()
stu2.submitHomeWork()
stu3.submitHomeWork()
# 发布订阅者模式
- 发布订阅模式和观察者模式的不同在于,增加了第三方即事件中心;目标对象状态的改变并直接通知观察者,而是通过第三方的事件中心来派发通知。
// 发布者
class Pub {
constructor (dispatcher) {
this.dispatcher = dispatcher
this.id = observed_ids++
}
/**
* @description: 发布方法
* @param {type} 通知类型
*/
publish(type) {
this.dispatcher.publish(type, this)
}
}
// 订阅者
class Subscriber {
constructor (dispatcher) {
this.dispatcher = dispatcher
this.id = observer_ids++
}
subscribe(type) {
this.dispatcher.subscribe(type, this)
}
doUpdate(type, arg) {
console.log('接受到消息' + arg)
}
}
// 调度中心
class Dispatcher {
constructor () {
this.dispatcher = {}
}
// 订阅
subscribe(pub, subscriber) {
if (!this.dispatcher[pub.id]) {
this.dispatcher[pub.id] = []
}
this.dispatcher[pub.id].push(subscriber)
}
// 退订
unsubscribe(pub, subscriber) {
const subscribers = this.dispatcher[type]
if (!subscribers || !subscribers.length) return
this.dispatcher[type] = subscribers.filter(item => {
return item.id !== subscriber.id
})
}
// 发布
publish(type, args) {
const subscribers = this.dispatcher[type]
if (!subscribers || !subscribers.length) return
subscribers.forEach(subscriber => {
subscriber.doUpdate(type, args)
})
}
}
class Reader extends Subscriber {
constructor (name, dispatcher) {
super(dispatcher)
this.name = name
}
doUpdate(type, st) {
// super.update(st);
console.log(this.name + `阅读了--${type}--公众号的文章`)
}
}
class WeiX extends Pub {
constructor (name, dispatcher) {
super(dispatcher)
this.name = name
}
publishArticle(type) {
this.publish(type)
}
}
const dispatcher = new Dispatcher()
// 公众号
const wei1 = new WeiX('前端', dispatcher)
const wei2 = new WeiX('数据库', dispatcher)
// 读者们
const reader1 = new Reader('小玲', dispatcher)
const reader2 = new Reader('小明', dispatcher)
const reader3 = new Reader('小李', dispatcher)
// 读者订阅公众号
reader1.subscribe('前端')
reader2.subscribe('数据库')
reader3.subscribe('数据库')
// 公众号发布文章
wei1.publishArticle('前端')
wei1.publishArticle('数据库')