通過上篇的介紹我們知道了觀察者模式的基本特點、使用場合以及如何以C++語言實現。有過多次編寫觀察者模式代碼經驗的你也許會發現,幾乎所有的案例存在為數相當可觀的重複性代碼:定義一個觀察者介面;定義一個主題並實現其諸如註冊一/多個觀察者,移除一/多個觀察者,廣播至所註冊的觀察者等基本行為。既然如此,我們有沒有可能為所有觀察者模式抽象出共有的介面與行為,以便日後複用呢?
此篇文章便是探討如何?一個通用或稱為萬能的觀察者模式庫。
我們為所有的觀察者/訂閱者抽象出一個共有的介面IObserver:
struct IObserver{
virtualvoidupdate()=0;
virtual~Observer(){}
};
當主題狀態發生改變時IObserver對象的update方法會被自動調用。IObserver的子類會實現update方法,以便具有其特定的行為。考慮到update方法的具體實現,大部分情況下我們需要查詢主題的狀態,從而做出反應。這有多種實現方案:一是產生全域或類似全域性(如Singleton技術)的主題對象:
Subjectg_subject;
...
structConcreteObserver:public IObjserver{
virtualvoidupdate(){
if(g_subject.getStatus()==xxx){
...
}
};
因為“儘可能的不要使用全域對象”緣故,這種方式不常用。二是為update方法增加一個參數,以便告知update某些必要的資訊,為具有普遍性,我以
Event代表此類,定義如下:
struct Event{
Event(Subject &subject);
BasicSubject*getSubject();
virtual~Event(){}
};
很明顯,這應該是個基類,所以具有需析構方法,此外,Event還提供一個擷取主題的方法。BasicSubject類是我們隨後要說到的主題基類。這樣,IObserver介面的定義看起來應該是這樣:
struct IObserver{
virtualvoidupdate(Event&event)=0;
virtual~IObserver(){}
};
接下來處理我們的主題,根據前面所提到的它應該具有的行為,它的定義應該大致像這樣:
class BasicSubject{
public:
virtual ~BasicSubject() {}
voidaddObserver(IObserver&observer);
voidremoveObserver(IObserver&observer);
protected:
voidnotifyAll(Event&event);
protected:
std::list<Observer*>observers_;
};