
你有沒有寫過這種 code:資料一更新,就要手動呼叫五個不同的 function 去更新 UI、發通知、寫 log?然後每次加一個新的「需要被通知的人」,就要回去改那段 code?
這就是 Observer Pattern 要解決的問題。
先講結論
Observer 就是「訂閱/發布」機制。資料變了(Subject),自動通知所有訂閱者(Observer)。你不用管有幾個訂閱者、他們是誰——你只管發布,剩下的交給機制。
classDiagram class Subject { -observers : Observer[] +subscribe(observer) void +unsubscribe(observer) void +notify() void } class Observer { <<interface>> +update(data)* void } class ConcreteObserverA { +update(data) void } class ConcreteObserverB { +update(data) void } Subject --> Observer Observer <|.. ConcreteObserverA Observer <|.. ConcreteObserverB
實戰:新聞訂閱系統
class NewsCategory {
constructor(categoryName) {
this.categoryName = categoryName;
this.subscribers = [];
}
subscribe(observer) {
if (!this.subscribers.includes(observer)) {
this.subscribers.push(observer);
}
}
unsubscribe(observer) {
this.subscribers = this.subscribers.filter(sub => sub !== observer);
}
notify(news) {
for (const subscriber of this.subscribers) {
subscriber.update(news);
}
}
publish(news) {
const fullNews = `[${this.categoryName}] ${news}`;
console.log(`發布:${fullNews}`);
this.notify(fullNews);
}
}
class User {
constructor(username) {
this.username = username;
}
update(news) {
console.log(`${this.username} 收到:${news}`);
}
}
const sports = new NewsCategory('體育');
const user1 = new User('小明');
const user2 = new User('小華');
sports.subscribe(user1);
sports.subscribe(user2);
sports.publish('台灣隊奧運奪金!');
sports.unsubscribe(user1);
sports.publish('世界盃結果出爐'); // 只有小華會收到你其實每天都在用 Observer
不騙你,這些東西底層都是 Observer Pattern:
- DOM 事件:
addEventListener就是在 subscribe - Node.js EventEmitter:
on('data', callback)就是 Observer - RxJS Observable:整個 library 就是 Observer Pattern 的強化版
- Vue/React 的響應式系統:資料一改,UI 自動更新
所以與其說「學 Observer Pattern」,不如說你是在理解這些工具背後的原理。
要注意什麼?
- 記得取消訂閱:不然就是 memory leak。前端開發者最常犯的錯——component unmount 的時候忘了
unsubscribe - 別讓通知風暴搞死你:一個 Subject 有 1000 個 Observer,每次更新全部通知?考慮 debounce 或 batch update
- 小心循環通知:A 通知 B、B 通知 A,然後 call stack overflow
Observer Pattern 就像 YouTube 的訂閱鈴鐺——你按了之後就不用一直去頻道主頁刷新,有新片自動通知你。只是現實中你訂閱了一百個頻道然後通知多到關掉。
延伸閱讀
- Strategy 模式 — 同屬行為型模式
- Mediator 模式 — 集中管理物件間互動
- Command 模式 — 將請求封裝成物件
- State 模式 — 以狀態驅動行為