1. 程式人生 > >觀察者模式實現老闆狀態變化通知 C++

觀察者模式實現老闆狀態變化通知 C++

說下對觀察者模式的理解:
觀察者模式定義了一種一對多的依賴關係, 讓多個觀察者物件可以同時監聽某一主題物件, 當這個主題物件的狀態發生改變的時候, 就會通知所有的觀察者物件, 使他們可以自動更新自己。
subject 類, 一般稱為主題類或者通知者類, 一般可以使用一個抽象類或者一個介面來實現, 他提供介面可以增加或者刪除觀察者物件。
observer 類, 一般使用抽象類或者介面實現。
當將一個系統分割成一系列相互協作的類的時候, 通常有個很不好的副作用,就是需要維護相關物件之間的一致性關係,但是, 我們又不希望因為需要維護一致性, 而造成各個類之間緊密耦合的現象, 這樣會給維護,擴充套件和重用帶來不便。
觀察者模式的使用情形:
當一個物件的改變需要同時改變其他物件的時候。並且他並不知道具體會有多少物件有待改變的時候, 就需要考慮使用觀察者模式了。


當一個抽象模型有兩個方面, 其中一方面依賴另一方面時, 使用觀察者模式可以將這兩者封裝在獨立的物件中, 使他們各自獨立的改變和複用。
觀察者模式實際上做的是解除耦合, 讓耦合的雙方都依賴於抽象, 而不是具體實現, 從而使得各自的變化都不會影響另一邊的變化。
當然, 觀察者模式有一個缺點:
抽象通知者還是依賴於抽象觀察者, 也就是說萬一沒有了抽象觀察者的這樣的介面, 就無法實現通知功能了。

virtual void Notify(){ for_each(objList.begin(), objList.end(), [](CIObserver * obj){obj->update()
; }); }

當我們需要,由客戶端指定通知物件的時候,這個模式就遇到了困難, .net 中為我們提供了事件委託機制, 可以解決這個問題, 這裡不再多說。

UML圖:
這裡寫圖片描述

執行效果圖:
這裡寫圖片描述

程式碼如下:
observer.h

#ifndef _OBSERVER_H_
#define _OBSERVER_H_

#include <string>
using std::string;

class CISubject;

/************************************************************************/
/* 觀察者基類                                                           *
/ /************************************************************************/ class CIObserver{ public: CIObserver(CISubject * sub, string name) : subject(sub), name(name){} virtual void update() = 0; protected: string name; CISubject * subject; }; #endif

mainobserver.h

#ifndef _MAINOBSERVER_H_
#define _MAINOBSERVER_H_

#include "observer.h"
#include "subject.h"
#include <string>
#include <iostream>

using std::string;
using std::cout;
using std::endl;

/************************************************************************/
/* 股票觀察者                                                           */
/************************************************************************/
class CStockObserver : public CIObserver{
public:
    CStockObserver(CISubject * subject, string name) : CIObserver(subject, name){}
    void update(){ cout << subject->SubjectState() << name << "關閉股票行情, 繼續工作" << endl; }
};

/************************************************************************/
/* NBA 觀察者                                                           */
/************************************************************************/
class CNBAObserver : public CIObserver{
public:
    CNBAObserver(CISubject * subject, string name) : CIObserver(subject, name){}
    void update(){ cout << subject->SubjectState() << name << "關閉NBA直播, 繼續工作" << endl; }
};

#endif // _MAINOBSERVER_H_

subject.h

#ifndef _SUBJECT_H_
#define _SUBJECT_H_

#include "observer.h"

#include <list>
#include <algorithm>
#include <string>

using std::list;
using std::string;

/************************************************************************/
/* 通知者介面                                                           */
/************************************************************************/
class CISubject{
public:
    virtual void Attach(CIObserver * obj){ objList.push_front(obj); }
    virtual void Detach(CIObserver * obj){ objList.pop_front(); }
    virtual void Notify(){ for_each(objList.begin(), objList.end(), [](CIObserver * obj){obj->update(); }); }

    string SubjectState() const { return subjectState; }
    void SubjectState(string val) { subjectState = val; }

private:
    list<CIObserver *> objList;
    string subjectState;
};

#endif // _SUBJECT_H_

mainsubject.h

#ifndef _MAINSUBJECT_H_
#define _MAINSUBJECT_H_

#include "subject.h"

/************************************************************************/
/* 通知者 boss                                                          */
/************************************************************************/
class CBoss : public CISubject{};

/************************************************************************/
/* 通知者 secretary                                                     */
/************************************************************************/
class CSecretary : public CISubject{};

#endif // _MAINSUBJECT_H_

main.cpp

#include "MainObserver.h"
#include "MainSubject.h"

#include <iostream>
#include <memory>

using namespace std;

int main(){
    shared_ptr<CBoss> boss(new CBoss);
    shared_ptr<CStockObserver> stock(new CStockObserver(boss.get(), "lisi"));
    shared_ptr<CNBAObserver> nba(new CNBAObserver(boss.get(), "zhangsan"));

    boss->Attach(stock.get());
    boss->Attach(nba.get());

    //boss->Detach(nba.get());

    boss->SubjectState("我是老闆, 我回來了, 大家有沒有認真工作啊?");
    boss->Notify();

    system("pause");
    return 0;
}