Table of Contents
Introduction
Observer Pattern 是一種行為設計模式,主要解決的是「如何在不緊密耦合主題和觀察者的情況下,使多個觀察者對象都能夠即時更新其狀態。」通過這種方式,任何關於主題的變更會立即通知所有註冊的觀察者。
什麼是 Observer Pattern
Observer Pattern(觀察者模式)其實就像是一個郵件訂閱系統。想像你訂閱了一家咖啡店的電子報,每當他們推出新品或有特價活動,你會收到通知。
在這個例子中,咖啡店就是「主題」,而你和其他訂閱了電子報的客戶就是「觀察者」。主題和觀察者之間不需要相互了解細節,只要主題有更新,所有的觀察者都會得到通知。
這樣的好處是,如果未來有更多人想訂閱咖啡店的電子報,或者有人想取消訂閱,咖啡店不需要做大的改動,只需要在觀察者列表中新增或移除人就好。
簡單來說,Observer Pattern 就是一個讓你能簡單地通知一群人(觀察者)有關某件事(主題)變動的方法。
什麼狀況適合使用 Observer Pattern
- 當你希望維護多個對象間的一致性,而不希望它們之間緊密耦合。
- 當一個對象的改變需要改變其他多個對象,但你又不確定會有多少對象需要改變。
範例教學
假設我們有一個咖啡店模擬程序,需要在新品種的咖啡推出時通知所有註冊的客戶。
原始範例 (未使用 Observer)
<?php
// 舊方法,需要手動更新每一個客戶
class CoffeeShop {
public $customers = [];
public function newCoffeeAvailable($coffeeType) {
foreach ($this->customers as $customer) {
// 假設每個客戶都有一個 notify 方法
$customer->notify("New coffee available: $coffeeType");
}
}
}
?>
缺點:這個方法會讓 CoffeeShop
和 Customer
緊密耦合,並且不易於擴展。
改善範例 (使用 Observer)
首先建立一個使用 Observer Pattern 的咖啡訂單追蹤系統。在這個範例中,CoffeeOrder
是主題,而 Customer
是觀察者。每當有新的咖啡訂單狀態更新,所有訂閱(觀察)該訂單的客戶會收到通知。
以下是具體的 PHP 程式碼:
這個例子的優點是,當 CoffeeOrder
的狀態更新時,所有訂閱這個訂單的 Customer
會自動得到通知,而我們不需要改變 CoffeeOrder
類別的程式碼。這樣增加了程式的靈活性和可擴展性。
更多延伸範例
觀察者模式(Observer Pattern)非常適合在多個對象之間建立一對多的依賴關係。除了上面的咖啡訂單追蹤範例外,這裡還有其他一些例子來展示類似用途。
假設咖啡店有不同種類的促銷活動,如「買一送一」或「會員日」等。我們可以使用觀察者模式來通知訂閱了不同促銷活動的客戶。
程式運作說明
- 我們定義了一個
Subject
介面和一個Observer
介面,以設定觀察者模式需要的基本方法。 Promotion
是Subject
的具體實現。它管理一個觀察者列表($observers
)和當前的促銷活動類型($promotionType
)。attach
方法用於添加新的觀察者,而detach
方法用於刪除觀察者。- 當促銷活動變更(
setPromotion
方法被調用)時,notify
方法會遍歷觀察者列表並調用他們的update
方法,將最新的促銷信息發送給他們。 - 我們創建了兩個
Customer
類的實例(Alice
和Bob
)並讓他們訂閱促銷活動。 - 當我們設定一個新的促銷活動時,所有訂閱的
Customer
(這裡是Alice
和Bob
)會收到更新通知。
這種設計讓我們可以簡單地添加或刪除觀察者,並且當促銷活動發生變更時,所有的觀察者都會自動獲得通知。這提供了一個高度解耦和可擴展的設計。
其他類似的 Design Pattern
類似的模式有「Publish-Subscribe Pattern」和「Event Aggregator」。
- Observer 通常是一對多。
- 而 Publish-Subscribe 可以是多對多。
- Event Aggregator 提供一個更集中的事件管理機制。