觀察者模式是一種行爲設計模式,容許一個對象將其狀態的改變通知其餘對象。前端
觀察者模式提供了一種做用於任何實現了訂閱者接口的對象的機制, 可對其事件進行訂閱和取消訂閱。typescript
圖片來源:https://refactoringguru.cn/design-patterns/observer設計模式
觀察者模式是一種在前端領域應用十分普遍的設計模式,特別是在圖形界面的組件中,若是你自定義了一個按鈕組件,那麼你極可能須要用到觀察者模式。dom
觀察者模式的核心成員有兩個,一個是做爲事件發佈者的Subject類,另外一個是做爲事件接收者的Observer類。測試
Subject類所具備的公共部分是對訂閱者的管理和向全部訂閱者發佈消息,而具體Subject所負責的業務邏輯須要放到各自的Subject類中。this
Subject接口設計
interface Subject { // 添加觀察者 attach(observer: Observer): void; // 移除觀察者 detach(observer: Observer): void; // 通知全部觀察者 notify(): void; }
具體Subject類code
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(); } }
觀察者只須要根據發佈者的發出的消息來判斷本身是否須要作出迴應便可。server
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();