本章主軸#
觀察者模式(Observer)解決一個常見問題:當某事件發生時,要通知一群「現在不確定有多少」的物件。它是「解耦」這件事最具代表性的模式。
模式分類略談#
GoF 把模式分為三類:
| 類別 | 用途 | 例子 |
|---|---|---|
| Creational(生成) | 建立物件 | Abstract Factory、Singleton、Factory Method |
| Structural(結構) | 串接既有物件 | Facade、Adapter、Bridge、Decorator |
| Behavioral(行為) | 容納可變的行為 | Strategy、Observer |
作者額外提出第四類:解耦類(decoupling)模式——目的是降低物件耦合,提升擴充性。Observer 是其中代表。
案例:新增客戶後要做什麼?#
新需求:每次新增客戶要:
- 寄歡迎信
- 用郵局服務驗證地址
直接寫死的做法#

Figure 18-1: 把通知行為寫死在 Customer 裡——加新需求就要改 Customer
把通知對象都寫進 Customer.add() 裡。問題:
- 需求一定會再變
- 加新動作要改
Customer - 不同公司可能要不同的歡迎信,需多版 Customer
GoF 對 Observer 的意圖描述#
在物件之間定義一對多的依賴關係;當某個物件改變狀態時,所有依賴者都會自動被通知並更新。
套到案例上的四步驟#
- 讓 Observer 共用同一個介面——Subject 才能用一致方式通知
- 由 Observer 自行向 Subject 註冊——
attach(Observer)/detach(Observer) - 事件發生時逐一呼叫
update——Subject 走過清單通知大家 - 提供查詢方法——Observer 可從 Subject 取得事件相關資訊
public class Customer {
static private Vector myObs = new Vector();
public static void attach(MyObserver o) { myObs.addElement(o); }
public static void detach(MyObserver o) { myObs.remove(o); }
public void notifyObs() {
for (Enumeration e = myObs.elements(); e.hasMoreElements();) {
((MyObserver) e.nextElement()).update(this);
}
}
}
interface MyObserver { void update(Customer c); }
Figure 18-2: 用 Observer 實作 Customer——WelcomeLetter 與 AddrVerification 自行向 Customer 註冊
加新需求很輕鬆#
新需求:對居住在實體店面 20 哩內的新客戶寄折扣券。
- 新增
BrickAndMortar觀察者,邏輯內自行過濾距離 - 不必動
Customer任何一行
既有類別可能無法修改?用 Adapter 包成符合 Observer 介面的 wrapper。
Observer 的關鍵特性#
| 欄位 | 內容 |
|---|---|
| Intent | 一對多依賴;狀態改變時所有依賴者自動更新 |
| Problem | 要通知一個會變動的物件清單 |
| Solution | Observer 主動註冊到 Subject;Subject 不必預知對象 |
| Consequences | 可能傳了 Observer 不需要的事件;可能要回查 Subject 取得資訊 |
| Implementation | Observer 註冊;事件發生時 Subject 呼叫 update;常與 Adapter 搭配 |

Figure 18-5: Observer 模式的通用結構——Subject 持有一群 Observer,狀態改變時自動通知
Java 內建支援#
java.util.Observable + Observer 介面內建實作。方法名為 addObserver / deleteObserver / notifyObservers。
實務筆記#
不是每個依賴都該用 Observer#
票務系統中「品項變動 → 重算稅」這種固定且已知的依賴,不適合用 Observer。它會徒增複雜度。
當依賴清單會變、是動態決定、依環境而異時,Observer 才有真正價值。
過濾不必要的通知#
可在 Subject 端用 Strategy 模式做過濾——每個 Observer 註冊時把自己的判斷策略一起傳入。
不同 Observer 要不同資訊#
同樣可用 Strategy:Observer 提供它要 Subject 怎麼回報的策略。
模式中的 OO 原則#
- 物件對自己負責:每個 Observer 自行抓資料、自行決定動作
- 抽象類別:Observer 介面表達「需被通知」的概念
- 多型封裝:Subject 不知具體 Observer 型別
本章重點#
- Observer 是把「不可預知的依賴方」這個變動軸封裝起來
- 讓事件來源不必預知所有可能的接收者
- 多種變化可組合:Adapter、Strategy 都常與 Observer 搭配
- 但別誤用——固定依賴不該硬塞 Observer