TS 設計模式07 - 觀察者模式

1. 簡介

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

2. 使用場景

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

3. 角色

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

4. 實現(xiàn)

image.png
interface Msg { // Msg 可以按照任意約定的接口格式去約束,這里假設是如下類型消息
    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 就是一種雙向關系(關聯(lián)和依賴)。另外曲横,這里的 setState 也只是對變更行為的一種抽象而已喂柒,你可以在任何事件或者任何時機通知訂閱者進行更新。

5. 小結

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

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

參考

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末弄屡,一起剝皮案震驚了整個濱河市题禀,隨后出現(xiàn)的幾起案子鞋诗,更是在濱河造成了極大的恐慌膀捷,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件削彬,死亡現(xiàn)場離奇詭異全庸,居然都是意外死亡,警方通過查閱死者的電腦和手機融痛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門壶笼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雁刷,你說我怎么就攤上這事覆劈。” “怎么了沛励?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵责语,是天一觀的道長。 經常有香客問我目派,道長坤候,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任企蹭,我火速辦了婚禮白筹,結果婚禮上智末,老公的妹妹穿的比我還像新娘。我一直安慰自己徒河,他們只是感情好系馆,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顽照,像睡著了一般它呀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棒厘,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天纵穿,我揣著相機與錄音,去河邊找鬼奢人。 笑死谓媒,一個胖子當著我的面吹牛,可吹牛的內容都是我干的何乎。 我是一名探鬼主播句惯,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼支救!你這毒婦竟也來了抢野?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤各墨,失蹤者是張志新(化名)和其女友劉穎指孤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贬堵,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡恃轩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了黎做。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叉跛。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蒸殿,靈堂內的尸體忽然破棺而出筷厘,到底是詐尸還是另有隱情,我是刑警寧澤宏所,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布酥艳,位于F島的核電站,受9級特大地震影響楣铁,放射性物質發(fā)生泄漏玖雁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一盖腕、第九天 我趴在偏房一處隱蔽的房頂上張望赫冬。 院中可真熱鬧浓镜,春花似錦、人聲如沸劲厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽补鼻。三九已至哄啄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間风范,已是汗流浹背咨跌。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留硼婿,地道東北人锌半。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像寇漫,于是被迫代替她去往敵國和親刊殉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354