-
中介者模式:一种行为型设计模式
-
应用场景:
一般来说,大型的软件在开发的过程中会使用模块化的开发方式。以我现在参与的项目举例,完整的软件包括交互、检索、算路、引导等等多个模块,这样有利于模块之间的独立开发,提高整体开发效率。
但是无论模块之间如何独立,总是会有需要模块间通信的时候。
例如用户通过界面交互,发起检索,这个过程需要交互与检索两模块间通信,将用户的意图由交互模块传递至检索模块。
这就会产生一个扩展性上的问题。如果模块有很多,且每个模块都向外提供了唯一的接收消息的接口,那么一个模块如果需要与其他所有模块通信,则需要记录其他所有模块的通信接口,同理每个模块都要记录所有与自己相关联的模块的通信接口。首先这就是一件很冗余并降低开发效率的事情。
其次,一旦有一天,某个模块修改了自己所提供的通信接口,或者增加了一个新模块,尤其是后者,在公司项目发展过程中是很正常的事情。那么所有模块关于其他模块通信接口的记录可能都需要修改或增加,这在拥有庞大模块数量的项目中,是很恐怖的事情。
此时可以考虑中介者模式。 -
举例:
假设现在有3个模块A B C
,MessageAB
是A B
间双向传递的一个消息,同理还有MessageAC、MessageBC
。
引入一个中介者,它手中记录着各模块的通信接口与通信协议,协议即是一种约定,A B
两模块间约定通过MessageAB
来传递某种信息,即是这两模块间的一个协议。模块间通信都将消息发给中介者,中介者无需关注消息具体用来传递什么信息,只需要关注协议双方,通过正确的通信接口转发消息,确保消息的转发对象正确即可,而消息的解析处理在接收模块内部进行。
这样如果有通信接口修改或增加新模块,协议双方将新协议告知中介者记录即可。 -
实现方式:
中介者对象中需要保存所有需转发消息的模块指针作为成员变量。
各模块类中也需要保存负责转发消息的中介者指针作为成员变量。
各模块类中需要实现发送与接收消息的方法。模块发送消息时调用中介者的转发接口,中介者确定接收目标后调用目标的接收接口。
下面代码中为了简化协议,我统一了各模块接收消息的接口名称。
以下是中介者模式的简单代码实现
#include <iostream>
using namespace std;
/*
* 约定三种协议
* MessageAB是AB模块间通信的消息
* MessageAC是AC模块间通信的消息
* MessageBC是BC模块间通信的消息
*/
enum Message
{
MessageAB,
MessageAC,
MessageBC,
};
class ModuleBase;
//中介者基类,提供转发接口
class MediatorBase
{
public:
virtual void Transmit(Message enMessage, ModuleBase* pFrom) = 0;
};
//模块基类,实现向外发消息的方法
class ModuleBase
{
public:
ModuleBase(MediatorBase* pMediator):m_pMediator(pMediator){}
//模块向外发消息的方法
void SendMessage(Message enMessage)
{
m_pMediator->Transmit(enMessage, this);
}
//模块接收消息的接口,由模块自己实现
virtual void vNotify(Message enMessage) = 0;
protected:
//每个模块内都有一份负责分发消息的中介者
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;
}
}
};
//中介者实现类
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);
//能通过dynamic_cast转换为不为NULL的指针,可确认指针指向的子类类型
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;
};
主函数中的使用
int main()
{
MediatorBase* pMediator = new ConcreteMediator();
//为所有模块指定中介者
ModuleBase* pModA = new ModuleA(pMediator);
ModuleBase* pModB = new ModuleB(pMediator);
ModuleBase* pModC = new ModuleC(pMediator);
//为中介者设定模块
ConcreteMediator* pConcreteMediator = dynamic_cast<ConcreteMediator*>(pMediator);
pConcreteMediator->SetModuleA(pModA);
pConcreteMediator->SetModuleB(pModB);
pConcreteMediator->SetModuleC(pModC);
//各模块间开始互发消息
pModA->SendMessage(MessageAC);
pModB->SendMessage(MessageBC);
pModC->SendMessage(MessageBC);
return 0;
}
控制台输出结果
ModuleC get MessageAC from ModuleA
ModuleC get MessageBC form ModuleB
ModuleB get MessageBC form ModuleC
如有错误,欢迎指正
网友评论