觀察者模式是一種行為設計模式,允許一個對象將其狀態的改變通知其他對象。 觀察者模式提供了一種作用於任何實現了訂閱者介面的對象的機制, 可對其事件進行訂閱和取消訂閱。 ...
觀察者模式是一種行為設計模式,允許一個對象將其狀態的改變通知其他對象。
觀察者模式提供了一種作用於任何實現了訂閱者介面的對象的機制, 可對其事件進行訂閱和取消訂閱。
圖片來源:https://refactoringguru.cn/design-patterns/observer
觀察者模式是一種在前端領域應用十分廣泛的設計模式,特別是在圖形界面的組件中,如果你自定義了一個按鈕組件,那麼你很可能需要用到觀察者模式。
觀察者模式的核心成員有兩個,一個是作為事件發佈者的Subject類,另一個是作為事件接收者的Observer類。
Subject部分
Subject類所具有的公共部分是對訂閱者的管理和向所有訂閱者發佈消息,而具體Subject所負責的業務邏輯需要放到各自的Subject類中。
Subject介面
interface Subject {
// 添加觀察者
attach(observer: Observer): void;
// 移除觀察者
detach(observer: Observer): void;
// 通知所有觀察者
notify(): void;
}
具體Subject類
class ConcreteSubject implements Subject {
// 發佈者狀態,測試使用
public state: number;
// 訂閱者名單
public observers: Array<Observer> = [];
// 管理訂閱方法
public attach(observer: Observer): void {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex !== -1) {
return console.log('已訂閱');
}
this.observers.push(observer);
console.log('訂閱成功');
}
public detach(observer: Observer): void {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex === -1) {
return console.log('訂閱者未訂閱');
}
this.observers.splice(observerIndex, 1);
console.log('訂閱者已移除');
}
public notify(): void {
console.log('通知所有訂閱者');
for (const observer of this.observers) {
observer.update(this);
}
}
// 訂閱管理以外的邏輯
public someLogic() {
this.state = Math.floor(Math.random() * 10 + 1);
console.log(`我更改了我的狀態:state=${this.state}`);
this.notify();
}
}
Observer部分
觀察者只需要根據發佈者的發出的消息來判斷自己是否需要做出回應即可。
Observer介面
interface Observer {
// 對發佈者發出的更新消息作出回應
update(subject: Subject): void;
}
具體Observer類
//具體觀察者A
class ConcreteObserverA implements Observer {
public update(subject: ConcreteSubject) {
if (subject.state <= 5) {
console.log('觀察者A作出回應');
}
}
}
// 具體觀察者B
class ConcreteObserverB implements Observer {
public update(subject: ConcreteSubject) {
if (subject.state > 5) {
console.log('觀察者B作出回應');
}
}
}
測試代碼
因為是隨機數,可能會得不到想要的結果,可以多嘗試幾次
const subject = new ConcreteSubject();
const observerA = new ConcreteObserverA();
subject.attach(observerA);
const observerB = new ConcreteObserverB();
subject.attach(observerB);
subject.someLogic();
subject.detach(observerB);
subject.someLogic();