觀察者模式
定義:也叫發佈訂閱模式,定義對象間一對多的依賴關係,使得每當一個對象改變(被觀察者(韓非子)),則所有依賴於它的對象(觀察者)都會得到通知並被自動更新。
通用類圖:
Subject被觀察者
定義被觀察者必須實現的職責,它必須能夠動態的增加,取消觀察者。它一般是抽象類或者實現類,僅僅完成作爲被觀察者必須實現的職責:管理觀察者並通知觀察者。
Observer觀察者
觀察者接收到消息後,即update操作,對接收到的信息進行處理。
ConcreteSubject具體的被觀察者
定義被觀察者自己的業務邏輯,同時定義對哪些事件進行通知。
ConcreteObserver具體的觀察者
每個觀察者在接收到消息後的處理反應是不同的,各個觀察者有自己的處理邏輯。
模式優點:觀察者與被觀察者之間是抽象耦合,如此設計,不管增加誰都是非常容易的。
建立一套觸發機制。
模式缺點:一個被觀察者,多個觀察者調試比較困難。(一般採用異步的方式)
使用場景:關聯行爲場景;事件多級觸發;跨系統的消息交換場景;
具體場景:
文件系統:例如在一個目錄下建立一個文件,這個動作同時通知目錄管理器增加該目錄,並通知磁盤管理器減少1KB空間.文件時被觀察者,其他倆是觀察者。
ATM機:比如你在ATM上取錢,多次輸錯密碼,卡就會被ATM吞掉,這時,會觸發哪些事件呢?1,攝像頭連拍;2,通知監控系統;3,初始化ATM;一般前兩個動作是觀察者模式來完成的,後一個動作是異常來完成的。
題示:
李斯,等人監控韓非子
類圖:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//觀察者接口
class Observer
{
public:
virtual void update(string context) = 0;
};
//具體觀察者
class LiSi:public Observer
{
public:
void update(string str)
{
cout<<"觀察到韓非子開始活動"<<endl;
this->reportToQiShiHuang(str);
cout<<"彙報完畢"<<endl;
}
void reportToQiShiHuang(string reportContext)
{
cout<<"韓非子有活動了: "<<reportContext<<endl;
}
};
class WangSi:public Observer
{
public:
void update(string str)
{
cout<<"觀察到韓非子開始活動"<<endl;
this->reportToQiShiHuang(str);
cout<<"彙報完畢"<<endl;
}
void reportToQiShiHuang(string reportContext)
{
cout<<"韓非子有活動了: "<<reportContext<<endl;
}
};
//被觀察者接口
class IHanFeiZi
{
public:
virtual void haveBreakfast() = 0 ;
virtual void haveFun()= 0 ;
};
//被觀察者接口
class Observable
{
public:
virtual void addObserver(Observer *observer) = 0;//增加觀察者
virtual void deleteObserver(Observer *observer) = 0 ;//刪除觀察者
virtual void notifyObserver(string context) = 0 ; //發生改變他應該有所動作通知觀察者
};
//被觀察者實現類
class HanFeiZi : public Observable,IHanFeiZi
{
private:
//定義一個變長數組,存放所有觀察者
vector<Observer*>observerList;
public:
void addObserver(Observer *observer)
{
this->observerList.push_back(observer);
}
void deleteObserver(Observer *observer)
{
vector<Observer*>::iterator key = find(observerList.begin(),observerList.end(),observer);
/*for(; key != observerList.end() ; key++)
{
Observer * keyPtr = *key;
if(*keyPtr == *observer)
break;
}*/
observerList.erase(key);
}
void notifyObserver(string context)
{
for(auto key : observerList)
key->update(context);
}
void haveBreakfast()
{
cout<<"韓非子吃飯了"<<endl;
//通知所有觀察者
this->notifyObserver("韓非子在吃飯");
}
void haveFun()
{
cout<<"韓非子在娛樂"<<endl;
//通知所有觀察者
this->notifyObserver("韓非子在娛樂");
}
};
int main()
{
Observer *liSi = new LiSi();
Observer *wangSi = new WangSi();
HanFeiZi hanfeizi;
hanfeizi.addObserver(liSi);
hanfeizi.addObserver(wangSi);
hanfeizi.haveBreakfast();
return 0;
}