Design Pattern-Observer === # 觀察者模式(Observer) * 為一種行為模式 * 使用時機 :描述一對多的依賴關係,當主題狀態發生變化會更新給觀察者知道,並且能添加或是減少觀察者 * * 目的 : * Subject有某個特定資訊在更新後需要讓Observer知道並做對應的動作 * 優點 : * Observer即Subject為抽象耦合關係,降低兩者的耦合關係。 * 建立了一套觸發機制。 * 缺點 : * 擴充不同的Observer在更新時可能接收到不必要的資訊 * 通常update會照順序,如果有一個Observer卡住會導致後面也卡住 * Observer過多的效能問題 # Flow chart  # Observer * 一個抽象類別用來定義接口,在收到Subject訊息後進行update * 以youtuber及訂閱者為例,訂閱者即Observer,因此我們定義一個抽象類Scriber ```cpp= class Scriber{ public: virtual void update(string program) = 0; }; ``` # ConcreteObserver * 將Observer做實現 * 訂閱者會收到新的影片名稱並收到更新通知 ```cpp= class ConcreteScriber : public Scriber{ public: string m_name; ConcreteScriber(string name):m_name(name){}; ~ConcreteScriber(){}; void update(string program) override{ cout << "Hi " << m_name << ", new video " << program << " is update." << endl; } }; ``` # Subject * 一個抽象類別用來定義被觀察者的接口,包含Attach(添加)、Detach(減少)及Notify(通知) * 定義一個Youtube的抽象類並用m_ObserverList來添加Scriber ```cpp= class Youtube{ public: Youtube(){}; ~Youtube(){}; virtual void attach(std::shared_ptr<Scriber> pObserver) = 0; virtual void detach(std::shared_ptr<Scriber> pObserver) = 0; virtual void notify(string program) = 0; set<std::shared_ptr<Scriber>> m_ObserverList; }; ``` # ConcreteSubject * 實現Subject各接口的細節 * attach : 在確認之前沒有這個人後添加上去 * detach : 將指定人員刪除 * notify : 呼叫每個subscribe的update告知說有新影片上線 ```cpp= class YoutubeChannel : public Youtube{ public: YoutubeChannel(){}; ~YoutubeChannel(){}; void attach(std::shared_ptr<Scriber> pObserver) override{ auto iter = std::find(m_ObserverList.begin(), m_ObserverList.end(), pObserver); if(iter==m_ObserverList.end()){ m_ObserverList.insert(pObserver); } } void detach(std::shared_ptr<Scriber> pObserver) override{ m_ObserverList.erase(pObserver); } void notify(string program) override{ for(auto iter: m_ObserverList){ iter->update(program); } } }; ``` # 實際輸出 * 可以看到新增三位Scriber後做notify可正常告知更新,且Sam被移除後Sam也不會接到通知 ```cpp= int main() { YoutubeChannel AnnoyOrange; shared_ptr<ConcreteScriber> Jack = make_shared<ConcreteScriber>("Jack"); shared_ptr<ConcreteScriber> Sam = make_shared<ConcreteScriber>("Sam"); shared_ptr<ConcreteScriber> Amy = make_shared<ConcreteScriber>("Amy"); AnnoyOrange.attach(Jack); AnnoyOrange.attach(Sam); AnnoyOrange.attach(Amy); AnnoyOrange.notify("Annoying orange ep1"); cout << "----------------------------" << endl; AnnoyOrange.detach(Sam); AnnoyOrange.notify("Annoying orange ep2"); return 0; } ```  source : https://ithelp.ithome.com.tw/articles/10249203 https://hypc-pub.github.io/design-patterns/patterns/observer-pattern.html github : https://github.com/GU-Lin/Design_Pattern_Practice/tree/main/Behavioral/Observer ###### tags : `Behavioral` `DesignPattern`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up