这是我参与8月更文挑战的第9天,活动详情查看: 8月更文挑战
观察者模式
核心:解决一对多的消息通信问题。 特点:观察者 :拥有一个更新的方法(收到通知的回调), 被观察对象 :拥有一个添加,删除,通知观察者的方法,和一个存放观察者的容器 手写思路
- 首先定义被观察对象
- 定义观察者
interface Subject {
observerList: Observer[];
addObserver: (observer: Observer) => void;
deleteObserver: (observer: Observer) => void;
notifyObservers: () => void;
}
interface Observer {
notify: () => void
}
注意要点
- 添加观察者就是把观察者加入观察者数组。
- 删除则通过 indexOf 找到下标,从列表移除。
- 通知则 forEach 调用观察者 notify方法。
- 需要进行各部分参数校验。
- 可以增加扩展方法,onece,clear 等等。
完整版本
interface Subject {
observerList: Observer[];
addObserver: (observer: Observer) => void;
deleteObserver: (observer: Observer) => void;
notifyObservers: () => void;
}
interface Observer {
notify: () => void
}
class CreatSubject implements Subject {
public observerList: Observer[] = []
public addObserver(observer: Observer): void {
this.observerList.push(observer);
}
public deleteObserver(observer: Observer): void {
let currentObserverIndex: number = this.observerList.indexOf(observer)
currentObserverIndex != -1 ? this.observerList.splice(currentObserverIndex, 1) : console.log('不存在该观察者')
}
public notifyObservers(): void {
this.observerList.forEach((observer) => {
observer.notify();
})
}
}
class CreatObserver implements Observer {
constructor(private name: string) { }
public notify(): void {
//观察者收到通知后的逻辑
console.log(`我是${this.name},我收到通知了`)
}
}
function testObserver(): void {
const classroom: Subject = new CreatSubject()
const coolFish: Observer = new CreatObserver('coolFish')
const teacherGuo: Observer = new CreatObserver('郭老师')
classroom.addObserver(coolFish)
classroom.addObserver(teacherGuo)
classroom.notifyObservers()
}
testObserver()
发布订阅者模式
核心: 解决多对多的消息通信问题。 特点:拥有三个类组成 发布者:发布的事件名称和数据。 订阅者:订阅事件名和收到订阅的回调函数。 事件中心:一个添加事件的方法,一个删除事件的方法,一个触发事件的方法 手写思路
interface Publisher {
subscriber: string;
data: any;
}
interface EventChannel {
subjects: { [key: string]: Function[] };
on: (subscriber: string, callback: () => void) => void;
off: (subscriber: string, callback: () => void) => void;
emit: (subscriber: string, data: any) => void;
}
interface Subscriber {
subscriber: string;
callback: () => void;
}
注意要点:
- 订阅者会为事件中心的监听事件提供订阅的事件名,和该事件触发时的回调。
- 发布者会为事件中心的触发事件提供触发事件的事件名,和携带的参数。
- 事件中心有一个事件中心列表,里面存放了事件,和对应的回调函数数组。
- 当有事件触发时,将该事件的值,那个装满回调函数的数组遍历触发。
完整代码
interface Publisher {
subscriber: string;
data: any;
}
interface EventBus {
subjects: { [key: string]: Function[] };
on: (subscriber: string, callback: () => void) => void;
off: (subscriber: string, callback: () => void) => void;
emit: (subscriber: string, data: any) => void;
}
interface Subscriber {
subscriber: string;
callback: () => void;
}
class CreateEventBus implements EventBus {
// 初始化订阅者对象,键为事件名,值为该事件的回调数组
public subjects: { [key: string]: Function[] } = {};
// 添加订阅事件
public on(subscriber: string, callback: () => void): void {
if (!this.subjects[subscriber]) {
this.subjects[subscriber] = [];
}
this.subjects[subscriber].push(callback);
};
// 取消事件
public off(subscriber: string, callback: () => void): void {
if (callback === null) {
this.subjects[subscriber] = [];
} else {
const index: number = this.subjects[subscriber].indexOf(callback);
~index && this.subjects[subscriber].splice(index, 1);
}
};
// 触发事件
public emit(subscriber: string, data = null): void {
console.log(`收到发布者信息,执行订阅事件:${subscriber}`);
this.subjects[subscriber].forEach(item => item(data));
};
}
class CreatePublisher implements Publisher {
public subscriber: string = "";
public data: any;
constructor(subscriber: string, data: any) {
this.subscriber = subscriber;
this.data = data;
}
}
class CreateSubscriber implements Subscriber {
public subscriber: string = "";
constructor(subscriber: string, callback: () => void) {
this.subscriber = subscriber;
this.callback = callback;
}
public callback(): void { };
}
小结: 从TS 来理解设计模式,主要就是利用接口即是核心,只要记住接口,然后灵活的实现该接口,你就掌握了该设计模式的手写。