C++示例講解觀察者設(shè)計模式
引言
用來解決兩個不相關(guān)對象之間的一對一或者一對多的通信模型。
什么是觀察者設(shè)計模式
觀察者模式是一種對象行為模式。它定義對象間的一種一對多的依賴關(guān)系, 當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。在觀察者模式中,主體是通知的發(fā)布者,它發(fā)出通知時并不需要知道誰是它的觀察者,可以有任意數(shù)目的觀察者訂閱并接受通知。觀察者模式不僅被廣泛應(yīng)用于軟件界面元素之間的交互,在業(yè)務(wù)對象之間的交互、權(quán)限管理等方面也有廣泛的應(yīng)用。
解決的問題
定義了對象間的一種一對多的組合關(guān)系,以便一個對象的狀態(tài)發(fā)生時,所有依賴于它的對象都得到通知并自動刷新。
觀察者和被觀察者之間存在“觀察”的邏輯關(guān)系,當(dāng)被觀察者發(fā)生變化時,觀察者就會觀察到這樣的變化,并作出相應(yīng)的響應(yīng)。
編程思路
設(shè)定兩者類,一個為觀察者類,一個為被觀察者類
觀察者類中,定義一個對某個事件感興趣的處理函數(shù),一般也叫做槽函數(shù)
被觀察者類中,定義一個數(shù)據(jù)結(jié)構(gòu),用來保存觀察者對某一個事件id(信號)感興趣,使用數(shù)據(jù)結(jié)構(gòu)建立信號與對象之間的映射關(guān)系
被觀察者類中,定義兩個方法函數(shù):
一個方法為:添加觀察者與其感興趣的事件id(信號)加入到容器中
另一個方法為:信號函數(shù):通知事件函數(shù)執(zhí)行邏輯:首先遍歷容器中,有沒有感興趣的事件ID,如果有,則代表一系列的觀察者,對這個事件感興趣,那么再次遍歷觀察者列表,讓每一個觀察者執(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信號,執(zhí)行1信號對應(yīng)的槽函數(shù)" << endl;
break;
case 2:
cout << this << "接收到2信號,執(zhí)行2信號對應(yīng)的槽函數(shù)" << endl;
break;
case 3:
cout << this << "接收到3信號,執(zhí)行3信號對應(yīng)的槽函數(shù)" << endl;
break;
case 4:
cout << this << "接收到4信號,執(zhí)行4信號對應(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 << "接收到未知信號,沒有對應(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;
}知識小百科
this指針:
- 是本對象的起始地址,用
const修飾的常地址(原型:stu *const this)(本文代碼中this的作用) - 是隱藏在成員函數(shù)(非靜態(tài)函數(shù))的最左側(cè)的常變量形參
作用:
- 區(qū)別成員屬性和成員函數(shù)的形參
- 解引用,返回本對象的地址
到此這篇關(guān)于C++示例講解觀察者設(shè)計模式的文章就介紹到這了,更多相關(guān)C++觀察者設(shè)計模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt(C++)調(diào)用工業(yè)相機Basler的SDK使用示例
這篇文章主要介紹了Qt(C++)調(diào)用工業(yè)相機Basler的SDK使用示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
C語言中判斷兩個IPv4地址是否屬于同一個子網(wǎng)的代碼
這篇文章主要介紹了C語言中判斷兩個IPv4地址是否屬于同一個子網(wǎng)的代碼,需要的朋友可以參考下2017-09-09
C++設(shè)計模式之簡單工廠模式的實現(xiàn)示例
這篇文章主要給大家介紹了關(guān)于C++設(shè)計模式之簡單工廠模式的相關(guān)資料,簡單工廠模式,主要用于創(chuàng)建對象,添加類時,不會影響以前的系統(tǒng)代碼,需要的朋友可以參考下2021-06-06

