TS 設(shè)計模式07 - 觀察者模式

1. 簡介

觀察者模式是一種對象行為模式。它定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。

2. 使用場景

  1. 當(dāng)一個抽象模型有兩個方面,其中一個方面依賴于另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復(fù)用。
  2. 當(dāng)對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象需要被改變。
  3. 當(dāng)一個對象必須通知其他對象,而它又不能假定其他對象是誰。換言之,不希望這些對象是緊密耦合的。

3. 角色

  1. 抽象主題(Subject):
    它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數(shù)量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
  2. 具體主題(Concrete Subject):
    將有關(guān)狀態(tài)存入具體觀察者對象;在具體主題內(nèi)部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。
  3. 抽象觀察者(Observer):
    為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
  4. 具體觀察者(Concrete Observer):
    實現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調(diào)。

4. 實現(xiàn)

image.png
interface Msg { // Msg 可以按照任意約定的接口格式去約束,這里假設(shè)是如下類型消息
    name: string;
    value: string;
}

interface Subject {
    registerObserver(observer: Observer): void;
    removeObserver(observer: Observer): void;
    notifyObservers(msg: Msg): void;
}

interface Observer {
    update(msg: Msg): void
}

class ConcreteSubject implements Subject {
    private observers: Observer[] = [];
    private state: object = {};
    registerObserver(observer: Observer): void {
        this.observers.push(observer);
    }
    removeObserver(observer: Observer): void {
        const index = this.observers.findIndex(val => val === observer);
        if (index > -1) {
            this.observers.splice(index, 1);
        }
    }
    notifyObservers(msg: Msg): void {
        this.observers.forEach(observer => observer.update(msg));
    }
    setState(name, value): void {
        this.state[name] = value;
        console.log(`${name}狀態(tài)更新為:${value}`);
        console.log('通知所有觀察者');
        this.notifyObservers({
            name,
            value,
        });
    }
}

class ConcreteObserver implements Observer {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    update(msg: Msg): void {
        console.log(`${this.name} 觀察到:${msg.name}狀態(tài)更新為:${msg.value}`);
    }
}

const concreteSubject = new ConcreteSubject();
const concreteObserver1 = new ConcreteObserver('小王');
const concreteObserver2 = new ConcreteObserver('小明');

concreteSubject.registerObserver(concreteObserver1);
concreteSubject.registerObserver(concreteObserver2);
concreteSubject.setState('天氣', '多云');

concreteSubject.removeObserver(concreteObserver2);
concreteSubject.setState('天氣', '晴');
image.png

這里的 Msg 其實就是一種約定的消息接口,你甚至可以直接使用 Subject,這樣Subject 和 Observer 就是一種雙向關(guān)系(關(guān)聯(lián)和依賴)。另外,這里的 setState 也只是對變更行為的一種抽象而已,你可以在任何事件或者任何時機(jī)通知訂閱者進(jìn)行更新。

5. 小結(jié)

當(dāng)一個對象密切關(guān)注另一個對象的某個狀態(tài)時,就可以使用觀察者模式。它解除了主題和具體觀察者的耦合,讓耦合的雙方都依賴于抽象,而不是依賴具體。

另外,在使用輪詢的地方,我們應(yīng)該先考慮是否可以使用觀察者模式。因為主動觀察是優(yōu)于被動輪詢的。

參考

觀察者模式 - 百度百科
觀察者模式 | 菜鳥教程
圖解23種設(shè)計模式(TypeScript版)——前端必修內(nèi)功心法
Java設(shè)計模式之觀察者模式(Observer Pattern)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容