-
中介者模式:一種行為型設(shè)計(jì)模式
-
應(yīng)用場(chǎng)景:
一般來(lái)說(shuō)叶撒,大型的軟件在開(kāi)發(fā)的過(guò)程中會(huì)使用模塊化的開(kāi)發(fā)方式禁荒。以我現(xiàn)在參與的項(xiàng)目舉例羽资,完整的軟件包括交互场航、檢索、算路袍榆、引導(dǎo)等等多個(gè)模塊胀屿,這樣有利于模塊之間的獨(dú)立開(kāi)發(fā),提高整體開(kāi)發(fā)效率包雀。
但是無(wú)論模塊之間如何獨(dú)立宿崭,總是會(huì)有需要模塊間通信的時(shí)候。
例如用戶通過(guò)界面交互才写,發(fā)起檢索葡兑,這個(gè)過(guò)程需要交互與檢索兩模塊間通信奖蔓,將用戶的意圖由交互模塊傳遞至檢索模塊。
這就會(huì)產(chǎn)生一個(gè)擴(kuò)展性上的問(wèn)題讹堤。如果模塊有很多吆鹤,且每個(gè)模塊都向外提供了唯一的接收消息的接口,那么一個(gè)模塊如果需要與其他所有模塊通信洲守,則需要記錄其他所有模塊的通信接口疑务,同理每個(gè)模塊都要記錄所有與自己相關(guān)聯(lián)的模塊的通信接口。首先這就是一件很冗余并降低開(kāi)發(fā)效率的事情梗醇。
其次知允,一旦有一天,某個(gè)模塊修改了自己所提供的通信接口叙谨,或者增加了一個(gè)新模塊温鸽,尤其是后者,在公司項(xiàng)目發(fā)展過(guò)程中是很正常的事情手负。那么所有模塊關(guān)于其他模塊通信接口的記錄可能都需要修改或增加涤垫,這在擁有龐大模塊數(shù)量的項(xiàng)目中,是很恐怖的事情竟终。
此時(shí)可以考慮中介者模式蝠猬。 -
舉例:
假設(shè)現(xiàn)在有3個(gè)模塊A B C
,MessageAB
是A B
間雙向傳遞的一個(gè)消息衡楞,同理還有MessageAC吱雏、MessageBC
敦姻。
引入一個(gè)中介者瘾境,它手中記錄著各模塊的通信接口與通信協(xié)議,協(xié)議即是一種約定镰惦,A B
兩模塊間約定通過(guò)MessageAB
來(lái)傳遞某種信息迷守,即是這兩模塊間的一個(gè)協(xié)議。模塊間通信都將消息發(fā)給中介者旺入,中介者無(wú)需關(guān)注消息具體用來(lái)傳遞什么信息兑凿,只需要關(guān)注協(xié)議雙方,通過(guò)正確的通信接口轉(zhuǎn)發(fā)消息茵瘾,確保消息的轉(zhuǎn)發(fā)對(duì)象正確即可礼华,而消息的解析處理在接收模塊內(nèi)部進(jìn)行。
這樣如果有通信接口修改或增加新模塊拗秘,協(xié)議雙方將新協(xié)議告知中介者記錄即可圣絮。 -
實(shí)現(xiàn)方式:
中介者對(duì)象中需要保存所有需轉(zhuǎn)發(fā)消息的模塊指針作為成員變量。
各模塊類(lèi)中也需要保存負(fù)責(zé)轉(zhuǎn)發(fā)消息的中介者指針作為成員變量雕旨。
各模塊類(lèi)中需要實(shí)現(xiàn)發(fā)送與接收消息的方法扮匠。模塊發(fā)送消息時(shí)調(diào)用中介者的轉(zhuǎn)發(fā)接口捧请,中介者確定接收目標(biāo)后調(diào)用目標(biāo)的接收接口。
下面代碼中為了簡(jiǎn)化協(xié)議棒搜,我統(tǒng)一了各模塊接收消息的接口名稱(chēng)疹蛉。
以下是中介者模式的簡(jiǎn)單代碼實(shí)現(xiàn)
#include <iostream>
using namespace std;
/*
* 約定三種協(xié)議
* MessageAB是AB模塊間通信的消息
* MessageAC是AC模塊間通信的消息
* MessageBC是BC模塊間通信的消息
*/
enum Message
{
MessageAB,
MessageAC,
MessageBC,
};
class ModuleBase;
//中介者基類(lèi),提供轉(zhuǎn)發(fā)接口
class MediatorBase
{
public:
virtual void Transmit(Message enMessage, ModuleBase* pFrom) = 0;
};
//模塊基類(lèi)力麸,實(shí)現(xiàn)向外發(fā)消息的方法
class ModuleBase
{
public:
ModuleBase(MediatorBase* pMediator):m_pMediator(pMediator){}
//模塊向外發(fā)消息的方法
void SendMessage(Message enMessage)
{
m_pMediator->Transmit(enMessage, this);
}
//模塊接收消息的接口可款,由模塊自己實(shí)現(xiàn)
virtual void vNotify(Message enMessage) = 0;
protected:
//每個(gè)模塊內(nèi)都有一份負(fù)責(zé)分發(fā)消息的中介者
MediatorBase* m_pMediator;
};
//模塊A
class ModuleA : public ModuleBase
{
public:
ModuleA(MediatorBase* pMediator):ModuleBase(pMediator){}
virtual void vNotify(Message enMessage)
{
switch(enMessage)
{
case MessageAB:
cout << "ModuleA get MessageAB from ModuleB" << endl;
break;
case MessageAC:
cout << "ModuleA get MessageAC from MoudleC" << endl;
break;
default:
break;
}
}
};
//模塊B
class ModuleB : public ModuleBase
{
public:
ModuleB(MediatorBase* pMediator):ModuleBase(pMediator){}
virtual void vNotify(Message enMessage)
{
switch(enMessage)
{
case MessageAB:
cout << "ModuleB get MessageAB from ModuleA" << endl;
break;
case MessageBC:
cout << "ModuleB get MessageBC form ModuleC" << endl;
break;
default:
break;
}
}
};
//模塊C
class ModuleC : public ModuleBase
{
public:
ModuleC(MediatorBase* pMediator):ModuleBase(pMediator){}
virtual void vNotify(Message enMessage)
{
switch(enMessage)
{
case MessageAC:
cout << "ModuleC get MessageAC from ModuleA" << endl;
break;
case MessageBC:
cout << "ModuleC get MessageBC form ModuleB" << endl;
break;
default:
break;
}
}
};
//中介者實(shí)現(xiàn)類(lèi)
class ConcreteMediator : public MediatorBase
{
public:
ConcreteMediator():m_pModA(NULL),m_pModB(NULL),m_pModC(NULL){}
void Transmit(Message enMessage, ModuleBase* pFrom)
{
switch(enMessage)
{
case MessageAB:
{
ModuleA* pFromWhere = dynamic_cast<ModuleA*>(pFrom);
//能通過(guò)dynamic_cast轉(zhuǎn)換為不為NULL的指針,可確認(rèn)指針指向的子類(lèi)類(lèi)型
if(NULL != pFromWhere)
{
m_pModB->vNotify(enMessage);
}
else
{
m_pModA->vNotify(enMessage);
}
}
break;
case MessageAC:
{
ModuleA* pFromWhere = dynamic_cast<ModuleA*>(pFrom);
if(NULL != pFromWhere)
{
m_pModC->vNotify(enMessage);
}
else
{
m_pModA->vNotify(enMessage);
}
}
case MessageBC:
{
ModuleB* pFromWhere = dynamic_cast<ModuleB*>(pFrom);
if(NULL != pFromWhere)
{
m_pModC->vNotify(enMessage);
}
else
{
m_pModB->vNotify(enMessage);
}
}
}
}
void SetModuleA(ModuleBase* pModuleA){m_pModA = pModuleA;}
void SetModuleB(ModuleBase* pModuleB){m_pModB = pModuleB;}
void SetModuleC(ModuleBase* pModuleC){m_pModC = pModuleC;}
private:
ModuleBase* m_pModA;
ModuleBase* m_pModB;
ModuleBase* m_pModC;
};
主函數(shù)中的使用
int main()
{
MediatorBase* pMediator = new ConcreteMediator();
//為所有模塊指定中介者
ModuleBase* pModA = new ModuleA(pMediator);
ModuleBase* pModB = new ModuleB(pMediator);
ModuleBase* pModC = new ModuleC(pMediator);
//為中介者設(shè)定模塊
ConcreteMediator* pConcreteMediator = dynamic_cast<ConcreteMediator*>(pMediator);
pConcreteMediator->SetModuleA(pModA);
pConcreteMediator->SetModuleB(pModB);
pConcreteMediator->SetModuleC(pModC);
//各模塊間開(kāi)始互發(fā)消息
pModA->SendMessage(MessageAC);
pModB->SendMessage(MessageBC);
pModC->SendMessage(MessageBC);
return 0;
}
控制臺(tái)輸出結(jié)果
ModuleC get MessageAC from ModuleA
ModuleC get MessageBC form ModuleB
ModuleB get MessageBC form ModuleC
如有錯(cuò)誤,歡迎指正