C++示例講解觀察者設(shè)計(jì)模式
引言
用來解決兩個(gè)不相關(guān)對(duì)象之間的一對(duì)一或者一對(duì)多的通信模型。
什么是觀察者設(shè)計(jì)模式
觀察者模式是一種對(duì)象行為模式。它定義對(duì)象間的一種一對(duì)多的依賴關(guān)系, 當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。在觀察者模式中,主體是通知的發(fā)布者,它發(fā)出通知時(shí)并不需要知道誰是它的觀察者,可以有任意數(shù)目的觀察者訂閱并接受通知。觀察者模式不僅被廣泛應(yīng)用于軟件界面元素之間的交互,在業(yè)務(wù)對(duì)象之間的交互、權(quán)限管理等方面也有廣泛的應(yīng)用。
解決的問題
定義了對(duì)象間的一種一對(duì)多的組合關(guān)系,以便一個(gè)對(duì)象的狀態(tài)發(fā)生時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。
觀察者和被觀察者之間存在“觀察”的邏輯關(guān)系,當(dāng)被觀察者發(fā)生變化時(shí),觀察者就會(huì)觀察到這樣的變化,并作出相應(yīng)的響應(yīng)。
編程思路
設(shè)定兩者類,一個(gè)為觀察者類,一個(gè)為被觀察者類
觀察者類中,定義一個(gè)對(duì)某個(gè)事件感興趣的處理函數(shù),一般也叫做槽函數(shù)
被觀察者類中,定義一個(gè)數(shù)據(jù)結(jié)構(gòu),用來保存觀察者對(duì)某一個(gè)事件id(信號(hào))感興趣,使用數(shù)據(jù)結(jié)構(gòu)建立信號(hào)與對(duì)象之間的映射關(guān)系
被觀察者類中,定義兩個(gè)方法函數(shù):
一個(gè)方法為:添加觀察者與其感興趣的事件id(信號(hào))加入到容器中
另一個(gè)方法為:信號(hào)函數(shù):通知事件函數(shù)執(zhí)行邏輯:首先遍歷容器中,有沒有感興趣的事件ID,如果有,則代表一系列的觀察者,對(duì)這個(gè)事件感興趣,那么再次遍歷觀察者列表,讓每一個(gè)觀察者執(zhí)行相應(yīng)的槽函數(shù)
#include <iostream> #include <map> #include <list> using namespace std; class RecvBase { public: RecvBase() { cout << "RecvBase structure" << endl; } virtual void slotFunctions(int msgid)=0; virtual ~RecvBase() { cout << "RecvBase destruct" << endl; } }; class Recv:public RecvBase { public: Recv() { cout << "Recv structure" << "---" << this << "---" << endl; } void slotFunctions(int msgid)override { switch(msgid) { case 1: cout << this << "接收到1信號(hào),執(zhí)行1信號(hào)對(duì)應(yīng)的槽函數(shù)" << endl; break; case 2: cout << this << "接收到2信號(hào),執(zhí)行2信號(hào)對(duì)應(yīng)的槽函數(shù)" << endl; break; case 3: cout << this << "接收到3信號(hào),執(zhí)行3信號(hào)對(duì)應(yīng)的槽函數(shù)" << endl; break; case 4: cout << this << "接收到4信號(hào),執(zhí)行4信號(hào)對(duì)應(yīng)的槽函數(shù)" << endl; break; } } ~Recv()override { cout << "Recv destruct" << endl; } }; class Sender { public: Sender() { cout << "sender structure" << endl; } map<int,list<RecvBase* >> RecvMap; void observerToRecvMap(int msgid,RecvBase* recv) { this->RecvMap[msgid].push_back(recv); } void senderSignals(int msgid) { auto it = RecvMap.find(msgid); if(it!=RecvMap.end()) { for(RecvBase* p:it->second) { p->slotFunctions(msgid); } }else{ cout << "接收到未知信號(hào),沒有對(duì)應(yīng)的可執(zhí)行槽函數(shù)" << endl; } } ~Sender() { cout << "sender destruct" << endl; } }; int main() { Sender sender; RecvBase* r1=new Recv(); RecvBase* r2=new Recv(); RecvBase* r3=new Recv(); RecvBase* r4=new Recv(); sender.observerToRecvMap(1,r1); sender.observerToRecvMap(1,r2); sender.observerToRecvMap(2,r2); sender.observerToRecvMap(3,r3); sender.observerToRecvMap(4,r4); while(true) { int msgid; cin >> msgid; if(-1==msgid)break; sender.senderSignals(msgid); } delete r1; delete r2; delete r3; delete r4; return 0; }
知識(shí)小百科
this指針:
- 是本對(duì)象的起始地址,用
const
修飾的常地址(原型:stu *const this
)(本文代碼中this的作用) - 是隱藏在成員函數(shù)(非靜態(tài)函數(shù))的最左側(cè)的常變量形參
作用:
- 區(qū)別成員屬性和成員函數(shù)的形參
- 解引用,返回本對(duì)象的地址
到此這篇關(guān)于C++示例講解觀察者設(shè)計(jì)模式的文章就介紹到這了,更多相關(guān)C++觀察者設(shè)計(jì)模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mac下使用Eclipse編譯C/C++文件出現(xiàn) launch failed, binary not found 解決方
這篇文章主要介紹了Mac下使用Eclipse編譯C/C++文件出現(xiàn) launch failed, binary not found 解決方案,需要的朋友可以參考下2014-10-10VisualStudio2022編寫C語言的實(shí)現(xiàn)步驟
VisualStudio2022是一款強(qiáng)大的集成開發(fā)環(huán)境,可以用來編寫C語言程序,本文主要介紹了VisualStudio2022編寫C語言的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06