[設計模式]觀察者模式
1. 觀察者模式解決什麼問題
觀察者模式解決「通知依賴問題」,比如乙個檔案過濾器,你要顯示進度,如何解決?我們最先想到的是裡面生成乙個通知方法,然後有關行為呼叫這個方法來進行通知。
如下面乙個**,是乙個檔案分割器,將乙個大檔案分割成很多小檔案;我們現在對其提出乙個進度條需求,我們首先想到的就是如下在檔案分割器中生成乙個進度條物件,分割時不斷更新進度條物件顯示進度。
可是,這存在什麼問題呢?對於一般開發者,這顯然並沒有什麼問題,但是如果對於物件導向,其違背原則如下:
依賴倒置原則:高層模組不能依賴底層模組,二者應該依賴於抽象;抽象不應該依賴於實現細節,實現細節應該依賴於抽象。
其 progressbar是乙個實現細節,比如今天是以進度條展示的,但是你明天如果使用別的方式展示,你還是要更改原始碼。
① 現在,你想更改這段**,你可以不依賴progressbar而是依賴其父類controlbase,但你發現,其controlbase並沒有setvalue這個方法,你這就走入了乙個死胡同。
② 現在,你往根本上思考,progressbar扮演了什麼樣的角色,其是乙個「通知」的角色,可以是使用乙個抽象的方式來表達通知而不是乙個具體的控制項來進行通知。
因此,現在就不要使用乙個具體的通知機制,而是使用乙個通知抽象類 progress,在建構函式中再傳入其具體的子類例項化該基類,這樣就完成了「從抽象到具體的轉變」。
③ 之後,mainform多繼承自progress,這樣介面和通知兩者就構成了依賴關係,與檔案分割器變成松耦合;而之前檔案分割器中存在通知的具體實現細節。
這樣,以後這個介面可以放在任何環境下,都支援乙個進度通知,可以被各種控制項使用,而不一定非得是分割器使用,也不用靠分割器來實現其細節。
④ 到目前為止,已經很好解決了依賴倒置原則,但是目前仍然存在乙個問題,如果要實現多個觀察者,應該如何去實現?其採用vector設計多個觀察者。
總結:觀察者模式也被稱為訂閱通知模式,即乙個事件完成時可以選擇通知到某個控制項中,這種關係意味著其兩者必須是松耦合而不是緊耦合,因為被觀察者可以選擇通知也可以選擇不通知,讓各個程式設計師根據需求來做出改變。
//檔案分割器
class
filesplitter
void
split()
}};//
檔案分割介面
class mainform : public
form
};
2. 修改**
根據上面的修改意見,我們將進度類作為乙個虛類,其派生出乙個進度條類,檔案分割器建構函式中存在乙個進度類,其初始化時作為進度條類的指標。
其也可以實現進度條可選,即多個建構函式,在分割時會檢查進度類指標是否為null,如果不為null,則呼叫通知。
這明顯,通過虛函式,原本進度條通知與檔案分割緊耦合,現在變為松耦合,檔案分割中沒有具體的通知實現細節,其實現細節由專門的進度通知的派生類去實現。
比如之後你想用標籤去實現通知,則直接將進度類派發出乙個然後呼叫即可。
#include #include#include
using
namespace
std;
//通知基類
class
iprogress //
虛析構函式
};//
實現進度條通知的類
class progressbar :public
iprogress
putchar(']
');printf(
"%3d%%
", (int)((double(current) / length) * 100
));
//游標回退,實現重新整理
for (int i = 0; i != length + 6; i++)
}};//
作為乙個主介面
class
window ;
//檔案分割器類
class
filesplit
//實現檔案分割
void
dofilesplit()
}};//
介面類class mainform : public
window
};int
main()
3. 更進一步修改
如果打算將其設計成一套桌面框架來使用,這裡還存在乙個問題:通知類與桌面類是松耦合,其關係不大。
但是我們預設,一般桌面類必須存在乙個通知類,只有這樣才能實現讓使用者直觀體現出其程序狀態。
從這個角度出發,我們將桌面類繼承自通知類,因為通知類是乙個虛函式,因此我們在桌面類中必須將其通知方法重寫,這樣就確保,如果生成乙個桌面,就必須實現其通知類,實現桌面與通知的緊耦合。
#include #include#include
using
namespace
std;
//通知基類
class
iprogress //
虛析構函式
};//
作為乙個主介面
class
window ;
//檔案分割器類
class
filesplit
//實現檔案分割
void
dofilesplit()
}};//
介面類class mainform : public window , public
iprogress
//例項化通知方式
virtual
void doprogress(const
int& current, const
int&length)
putchar(']
');printf(
"%3d%%
", (int)((double(current) / length) * 100
));
//游標回退,實現重新整理
for (int i = 0; i != length + 6; i++)
}};int
main()
python 設計模式 觀察者 觀察者設計模式
在觀察者設計模式這種模式中,物件被表示為等待事件觸發的觀察者。一旦發生指定的事件,觀察者就會關注該主體。當事件發生時,主體告訴觀察者它已經發生。以下uml圖表示觀察者模式 如何實現觀察者模式?現在讓我們來看看如何實現觀察者模式。參考以下實現 import threading import time ...
設計模式 觀察者模式
觀察者模式定義了物件間一對多的依賴關係,乙個物件發生變化時,所有依賴它的物件都得到通知並被自動更新。本文主要闡述觀察者模式在分布式scada人機介面中的使用,利用這種模式使得人機介面顯示效率更高。發布者 郵局 觀察者 參與者 讀者 訂閱者 當郵局收到報社新雜誌的時候,即郵局狀態發生了改變,於是郵局把...
設計模式 觀察者模式
核心思想 註冊 通知 撤銷註冊 observer 將自己註冊到被觀察物件 subject 中,被觀察物件將觀察者存放在乙個容器 container 裡。被觀察物件發生了某種變化 如圖中的somechange 從容器中得到所有註冊過的觀察者,將變化通知觀察者。觀察者告訴被觀察者要撤銷觀察,被觀察者從容...