中介者模式
如果在一个系统中,各个对象之间存在多对多的相互关系,可以将对象之间的一些交互行为从各个对象中分离出来,集中封装在一个中介者对象中,使其耦合松散,并由中介者统一协调。
通过中介者,对象之间的多对多关系就简化为了更简单的一对多的关系。
中介者模式:定义一个对象来封装一系列对象的交互。中介者模式使各个对象之间不需要显示地相互引用,从而使其耦合松散,而且用户可以独立地改变它们之间的交互。
中介者模式简介
由图可知,中介者模式主要有以下角色:
- Mediator(抽象中介者):声明一个用于与各个同事对象之间交互的接口,通常声明一个注册方法,用于增加同事对象;
- ConcreteMediator(具体中介者):实现上面的接口,协调各个同事对象来实现协作行为,维持对各个同事对象的引用;
- Colleague(抽象同事类):声明各个同事类公有的接口,同时维持了一个对抽象中介者类的引用;
- ConcreteColleague(具体同事类): 具体实现接口,具体同事类只需与中介者通信,通过中介者完成与其他同事类的通信。
中介者代码实例
#include <iostream>
using namespace std;
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);
pColleague2->Send(message);
return 0;
}
中介者模式总结
优缺点
- 减少了子类生成,Mediator将原本分布于多个对象间的行为集中在一起。改变这些行为只需生成Meditator的子类即可。这样各个Colleague类可被重用;
- 它将各Colleague解耦,Mediator有利于各Colleague间的松耦合。你可以独立的改变和复用各Colleague类和Mediator类;
- 它简化了对象协议,用Mediator和Colleague间的一对多的交互来代替多对多的交互。一对多的关系更容易理解、维护和扩展;
- 它对对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,使你将注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清楚一个系统中的对象是如何交互的;
- 它使控制集中化,中介者模式将交互的复杂性变为中介者的复杂性。因为中介者封装了协议,它可能变得比任一个Colleague都复杂。这可能使得中介者自身成为一个难于维护的庞然大物。
使用场合
在下列情况下使用中介者模式:
- 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解;
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象;
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类。