Observer(觀察者)是一種設計模式,其中,一個對象(稱為subject)維持一係列依賴於它(觀察者)的對象,將有關狀態的任何變更自動通知給它們(見圖9-3)。當一個目標需要告訴觀察者發生了什麼有趣的事情,它會向觀察者廣播一個通知(可以包括與通知主題相關的特定數據)。
圖9-3 Observer模式
當我們不再希望某個特定的觀察者獲得其注冊目標發出的改變通知時,該目標可以將它從觀察者列表中刪除。
參考之前發布的設計模式定義通常是很有用的,它與語言無關,以便久而久之使其使用和優勢變得更有意義。“四人組”所著書籍(《設計模式:可複用麵向對象軟件的基礎》)中提供的Observer模式的定義是:
“一個或多個觀察者對目標的狀態感興趣,它們通過將自己依附在目標對象上以便注冊所感興趣的內容。目標狀態發生改變並且觀察者可能對這些改變感興趣,就會發送一個通知消息,調用每個觀察者的更新方法。
當觀察者不再對目標狀態感興趣時,它們可以簡單地將自己從中分離。”
現在我們可以擴展所學到的內容來使用以下組件實現Observer模式:
Subject(目標)
維護一係列的觀察者,方便添加或刪除觀察者Observer(觀察者)為那些在目標狀態發生改變時需獲得通知的對象提供一個更新接口ConcreteSubject(具體目標)狀態發生改變時,向Observer發出通知,儲存ConcreteObserver的狀態ConcreteObserver(具體觀察者)
存儲一個指向ConcreteSubject的引用,實現Observer的更新接口,以使自身狀態與目標的狀態保持一致
首先,讓我們來模擬一個目標可能擁有的一係列依賴Observer:
function ObserverList(){ }
ObserverList.prototype.Add = function(obj){ };
ObserverList.prototype.Empty = function(){ };
ObserverList.prototype.Count = function(){ };
ObserverList.prototype.Get = function (index){ this.observerList = [];
return this.observerList.push(obj);
this.observerList = [];
return this.observerList.length;
if (index > -1 && index Add New Observer checkbox
如下是樣例腳本:
// 引用DOM元素
var controlCheckbox = document.getElementById("mainCheckbox"),
addBtn = document.getElementById("addNewObserver"),
container = document.getElementById("observersContainer");
// 具體目標 Concrete Subject
// 利用Subject擴展controlCheckbox
extend(new Subject(), controlCheckbox);
// 點擊checkbox會觸發通知到觀察者上
controlCheckbox["onclick"] = new Function("controlCheckbox.Notify (controlCheckbox.checked)");
addBtn["onclick"] = AddNewObserver;
// 具體觀察者 Concrete Observer
function AddNewObserver() {
// 創建需要添加的新checkbox
var check = document.createElement("input");
check.type = "checkbox";
// 利用Observer類擴展checkbox
extend(new Observer(), check);
// 重寫自定義更新行為
this.checked = value;
check.Update = function (value) {
};
// 為主subject的觀察者列表添加新的觀察者
controlCheckbox.AddObserver(check);
// 將觀察者附件到容器上
container.appendChild(check);
}
在本例中,我們了解了如何實現和使用Observer模式,包含目標(Subject)、觀察者(Observer)、具體目標(ConcreteSubject)和具體觀察者(ConcreteObserver)的概念。
9.5.1 Observer(觀察者)模式和Publish/Subscribe(發布/訂閱)模式的區別
通常在JavaScript裏,注重Observer模式是很有用的,我們會發現它一般使用一個被稱為Publish/Subscribe(發布/訂閱)模式的變量來實現。雖然這些模式非常相似,但是它們之間的幾點區別也是值得注意的。
Observer模式要求希望接收到主題通知的觀察者(或對象)必須訂閱內容改變的事件,如圖9-4所示。
圖9-4 Publish/Subscribe
Publish/Subscribe模式使用了一個主題/事件通道,這個通道介於希望接收到通知(訂閱者)的對象和激活事件的對象(發布者)之間。該事件係統允許代碼定義應用程序的特定事件,這些事件可以傳遞自定義參數,自定義參數包含訂閱者所需的值。其目的是避免訂閱者和發布者之間產生依賴關係。
這與Observer模式不同,因為它允許任何訂閱者執行適當的事件處理程序來注冊和接收發布者發出的通知。
下麵這個示例說明了如果有publish()、subscribe()和unsubscribe()的功能實現,是如何使用Publish/Subscribe模式的:
// 非常簡單的mail處理程序// 接收到的消息數量