C++設(shè)計(jì)模式之中介者模式
前言
我們都知道,這個(gè)國際政治是一門很深的學(xué)問,不玩政治的人是搞不懂的。那么多的國家,國家之間的關(guān)系又及其復(fù)雜;就好比現(xiàn)在,美國和中國有經(jīng)濟(jì)利益關(guān)系,美國又和日本有盟友關(guān)系,朝鮮又和中國有說不清道不明的關(guān)系;這些復(fù)雜的關(guān)系,稍微處理不好,就可能引發(fā)局部戰(zhàn)爭,更有可能引發(fā)第三次世界大戰(zhàn)。如果出現(xiàn)了國與國之間出現(xiàn)了利益糾紛,那么該怎么辦呢?這個(gè)時(shí)候,聯(lián)合國出現(xiàn)了。聯(lián)合國就是一個(gè)處理國與國之間糾紛的中介者。
中介者模式
在GOF的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對(duì)中介者模式是這樣說的:用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。
我們都知道,面向?qū)ο笤O(shè)計(jì)鼓勵(lì)將行為分布到各個(gè)對(duì)象中。但是,這種分布可能會(huì)導(dǎo)致對(duì)象間有許多連接。在最壞的情況下,每一個(gè)對(duì)象都知道其他所有對(duì)象,就造成了復(fù)雜的關(guān)聯(lián)關(guān)系。雖然將一個(gè)系統(tǒng)分割成許多對(duì)象通常可以增強(qiáng)可復(fù)用性,但是對(duì)象間相互連接的激增又會(huì)降低其可復(fù)用性。大量的相互連接使得一個(gè)對(duì)象似乎不太可能在沒有其他對(duì)象的支持下工作,這樣使得系統(tǒng)表現(xiàn)為一個(gè)不可分割的整體。而且,對(duì)系統(tǒng)的行為進(jìn)行任何較大的改動(dòng)都十分困難,因?yàn)樾袨楸环植荚谠S多對(duì)象中。結(jié)果是,你可能不得不定義很多子類以定制系統(tǒng)的行為。
問題再回到聯(lián)合國的問題上來,在聯(lián)合國還沒有成立時(shí),國與國之間的關(guān)系是這樣的:
當(dāng)聯(lián)合國成立以后,國與國之間出現(xiàn)糾紛時(shí),是這樣的:
聯(lián)合國的成立,讓很多關(guān)系簡單化了,讓問題的處理也簡單化了,使國與國之間因?yàn)榧m紛產(chǎn)生摩擦的幾率減小了,讓世界更和平了。
UML類圖
Mediator:中介者,它定義了一個(gè)接口用于與各個(gè)Colleague對(duì)象通信;
ConcreteMediator:具體的中介者,它通過協(xié)調(diào)各Colleague對(duì)象實(shí)現(xiàn)協(xié)作行為;并了解和維護(hù)它的各個(gè)Colleague;
Colleague:同事類,每一個(gè)同事類都知道它的中介者對(duì)象;每一個(gè)同時(shí)對(duì)象在需要與其他的同事通信的時(shí)候,而是與它的中介者通信。
它們之間是按照以下方式進(jìn)行協(xié)作的:
同事向一個(gè)中介者對(duì)象發(fā)送和接收請(qǐng)求。中介者在各同事間適當(dāng)?shù)剞D(zhuǎn)發(fā)請(qǐng)求以實(shí)現(xiàn)協(xié)作行為。
使用場合
在下列情況下使用中介者模式:
1.一組對(duì)象以定義良好但是復(fù)雜的方式進(jìn)行通信。產(chǎn)生的相互依賴關(guān)系結(jié)構(gòu)混亂且難以理解;
2.一個(gè)對(duì)象引用其他很多對(duì)象并且直接與這些對(duì)象通信,導(dǎo)致難以復(fù)用該對(duì)象;
3.想定制一個(gè)分布在多個(gè)類中的行為,而又不想生成太多的子類。
優(yōu)缺點(diǎn)
1.減少了子類生成,Mediator將原本分布于多個(gè)對(duì)象間的行為集中在一起。改變這些行為只需生成Meditator的子類即可。這樣各個(gè)Colleague類可被重用;
2.它將各Colleague解耦,Mediator有利于各Colleague間的松耦合。你可以獨(dú)立的改變和復(fù)用各Colleague類和Mediator類;
3.它簡化了對(duì)象協(xié)議,用Mediator和Colleague間的一對(duì)多的交互來代替多對(duì)多的交互。一對(duì)多的關(guān)系更容易理解、維護(hù)和擴(kuò)展;
4.它對(duì)對(duì)象如何協(xié)作進(jìn)行了抽象,將中介作為一個(gè)獨(dú)立的概念并將其封裝在一個(gè)對(duì)象中,使你將注意力從對(duì)象各自本身的行為轉(zhuǎn)移到它們之間的交互上來。這有助于弄清楚一個(gè)系統(tǒng)中的對(duì)象是如何交互的;
5.它使控制集中化,中介者模式將交互的復(fù)雜性變?yōu)橹薪檎叩膹?fù)雜性。因?yàn)橹薪檎叻庋b了協(xié)議,它可能變得比任一個(gè)Colleague都復(fù)雜。這可能使得中介者自身成為一個(gè)難于維護(hù)的龐然大物。
代碼實(shí)現(xiàn)
實(shí)現(xiàn)一個(gè)通用的中介者模式:
#include <iostream>
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
class Mediator;
class Colleague
{
public:
Colleague(Mediator *pMediator) : m_pMediator(pMediator){}
virtual void Send(wchar_t *message) = 0;
protected:
Mediator *m_pMediator;
};
class ConcreteColleague1 : public Colleague
{
public:
ConcreteColleague1(Mediator *pMediator) : Colleague(pMediator){}
void Send(wchar_t *message);
void Notify(wchar_t *message)
{
wcout<<message<<endl;
}
};
class ConcreteColleague2 : public Colleague
{
public:
ConcreteColleague2(Mediator *pMediator) : Colleague(pMediator){}
void Send(wchar_t *message);
void Notify(wchar_t *message)
{
cout<<"ConcreteColleague2 is handling the message."<<endl;
wcout<<message<<endl;
}
};
class Mediator
{
public:
virtual void Sent(wchar_t *message, Colleague *pColleague) = 0;
};
class ConcreteMediator : public Mediator
{
public:
// The mediator forward the message
void Sent(wchar_t *message, Colleague *pColleague)
{
ConcreteColleague1 *pConcreteColleague1 = dynamic_cast<ConcreteColleague1 *>(pColleague);
if (pConcreteColleague1)
{
cout<<"The message is from ConcreteColleague1. Now mediator forward it to ConcreteColleague2"<<endl;
if (m_pColleague2)
{
m_pColleague2->Notify(message);
}
}
else
{
if (m_pColleague1)
{
m_pColleague1->Notify(message);
}
}
}
void SetColleague1(Colleague *pColleague)
{
m_pColleague1 = dynamic_cast<ConcreteColleague1 *>(pColleague);
}
void SetColleague2(Colleague *pColleague)
{
m_pColleague2 = dynamic_cast<ConcreteColleague2 *>(pColleague);
}
private:
// The Mediator knows all the Colleague
ConcreteColleague1 *m_pColleague1;
ConcreteColleague2 *m_pColleague2;
};
void ConcreteColleague1::Send(wchar_t *message)
{
// The second parameter mark where the message comes from
m_pMediator->Sent(message, this);
}
void ConcreteColleague2::Send(wchar_t *message)
{
m_pMediator->Sent(message, this);
}
int main()
{
// Create the mediator
Mediator *pMediator = new ConcreteMediator();
Colleague *pColleague1 = new ConcreteColleague1(pMediator);
Colleague *pColleague2 = new ConcreteColleague2(pMediator);
ConcreteMediator *pConcreteMediator = dynamic_cast<ConcreteMediator *>(pMediator);
pConcreteMediator->SetColleague1(pColleague1);
pConcreteMediator->SetColleague2(pColleague2);
wchar_t message[260] = L"Where are you from?";
pColleague1->Send(message);
return 0;
}
與外觀模式的區(qū)別
我在看中介者模式時(shí),第一眼就感覺中介者模式和外觀模式超級(jí)像。外觀模式與中介者模式的不同之處在于它是對(duì)一個(gè)對(duì)象子系統(tǒng)進(jìn)行抽象,從而提供了一個(gè)更為方便的接口;外觀模式的協(xié)議是單向的,即外觀模式向子系統(tǒng)提出請(qǐng)求,但反過來則不行;而對(duì)于中介者模式,是進(jìn)行多個(gè)對(duì)象之間的協(xié)作,通信是多向的。
總結(jié)
中介者模式是一個(gè)比較簡單的設(shè)計(jì)模式,我在這里對(duì)中介者模式進(jìn)行總結(jié),希望對(duì)大家有用。這篇也是蛇年的最后一篇文章了。馬年見了,在這里提前祝愿大家馬年快樂。
- php設(shè)計(jì)模式 Mediator (中介者模式)
- Javascript 中介者模式實(shí)例
- Javascript 模式實(shí)例 中介者模式
- javascript設(shè)計(jì)模式之中介者模式Mediator
- Java設(shè)計(jì)模式之中介者模式(Mediator Pattern)簡介
- 詳解iOS應(yīng)用的設(shè)計(jì)模式開發(fā)中Mediator中介者模式的使用
- 學(xué)習(xí)JavaScript設(shè)計(jì)模式之中介者模式
- 詳解Java設(shè)計(jì)模式編程中的中介者模式
- 深入理解JavaScript系列(36):設(shè)計(jì)模式之中介者模式詳解
- 輕松掌握java中介者模式
相關(guān)文章
Qt音視頻開發(fā)之利用ffmpeg實(shí)現(xiàn)解碼本地?cái)z像頭
一開始用ffmpeg做的是視頻流的解析,后面增加了本地視頻文件的支持,到后面發(fā)現(xiàn)ffmpeg也是支持本地?cái)z像頭設(shè)備的,所以本文就來用ffmpeg實(shí)現(xiàn)解碼本地?cái)z像頭功能吧2023-03-03在Visual Studio使用C++開發(fā)Metro應(yīng)用
這篇文章主要介紹了在Visual Studio使用C++開發(fā)Metro應(yīng)用的示例,盡管只是一個(gè)Hello world,但可以體現(xiàn)出VS下為開發(fā)者提供的方便,需要的朋友可以參考下2015-07-07C/C++ 獲取Windows系統(tǒng)的位數(shù)32位或64位的實(shí)現(xiàn)代碼
這篇文章主要介紹了C/C++ 獲取Windows系統(tǒng)的位數(shù)32位或64位的實(shí)現(xiàn)代碼的相關(guān)資料,希望通過本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10C++ 關(guān)于MFC List Control 控件的總結(jié)
這篇文章主要介紹了C++ 關(guān)于MFC List Control 控件的總結(jié)的相關(guān)資料,十分的詳細(xì),有需要的朋友可以參考下2015-06-06C語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)和雙向鏈表操作
這篇文章主要介紹了C語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)雙向鏈表操作,需要的朋友可以參考下2017-03-03深入淺析C/C++語言結(jié)構(gòu)體指針的使用注意事項(xiàng)
這篇文章主要介紹了C/C++語言結(jié)構(gòu)體指針的使用,大家都知道指針在32位系統(tǒng)占用4Byte,在64位系統(tǒng)占用8Byte,下面看下c語言代碼例子2021-12-12