意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。
动机:
面向对象设计鼓励将行为分布到各个对象中。这种分布可能会导致对象间有许多连接。最坏的情况,每个对象都知道其他所有对象。
虽然将一个系统分割成许多对象通常可以增强可复用性,但是对象间相互连接的激增又会降低其复用性。
通过将集体行为封装在一个单独的中介者对象中。中介者负责控制和协调一组对象间的交互。中介者充当一个中介以使组中的对象不再显示相互引用。这些对象仅知道中介者,从而减少了相互连接的数目。
适用性:
以下情况使用中介者模式:
1一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
2一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
3想定制一个分布在多个类中的行为,而又不想生成太多的子类。
结构:
参与者:
Mediator:中介者定义一个接口用于与各同事对象通信。
ConcreteMediator:具体中介者通过协调同事对象实现协作行为。了解并维护它的各个同事。
Colleagueclass(同事类):
每一个同事类都知道它的中介者对象。
每一个同事对象在需与其他的同事对象通信的时候,与它的中介者通信。
如下图:
协作:
同事向一个中介者对象发送和接收请求。中介者在各个同事间适当的转发请求以实现协作行为
效果(有以下优缺点):
1减少了子类生成,mediator将对象间的行为集中在一起,改变这些行为只需生成mediator子类即可,各个colleague类可被重用
2将各Colleague解耦:实现了松耦合,可以独立的改变和复合各Colleague和Mediator类
3简化了对象协议:一对多的交互来代替多对多的交互
4对对象如何协作进行了抽象。
5使控制集中化:可能使得中介者成为一个难以维护的庞然大物。(缺点)
实现:
1忽略抽象的Mediator类:当各colleague仅与一个mediator一起工作时,则只需要一个mediator
2Colleague-Mediator通信,两种实现方式:
(1)使用observer模式,mediator实现为observer,各colleague作为subject,一但状态改变则发通知给mediator,mediator做出的相应就是将状态改变的结果传播给其他colleague
(2)在mediator中定义一个特殊的通知接口,各colleague在通讯时直接调用该接口。
相关模式:
Facade与中介者的不同之处在于它是对一个对象子系统进行抽象,从而提供了一个更为方便的接口。它的协议是单向的,即Facade对象对这个子系统类提出请求,但反之则不行。而Mediator提供了各Colleague对象不支持或不能支持的协作行为,而且协议是多向的。
Colleague可使用Observer模式与Mediator通信。
代码:
//中介者模式
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
class Country;
//联合国机构类,相当于Mediator类
class UnitedNations
{
public:
virtual void Declare(string message, Country& colleage) = 0;
};
//国家类,相当于Colleage类
class Country
{
public:
Country(UnitedNations& mediator) :
_mediator(&mediator) { }
virtual ~Country()
{
}
protected:
UnitedNations* _mediator;
};
//美国类,相当于ConcreteColleague类
class USA : public Country
{
public:
USA(UnitedNations& mediator) : Country(mediator)
{}
//声明
void Declare(string message)
{
_mediator->Declare(message, *this);
}
void GetMessage(string message)
{
cout << "美国获得对方信息:" << message << endl;
}
};
//伊拉克类,相当于ConcreteColleague类
class Iraq : public Country
{
public:
Iraq(UnitedNations& mediator) : Country(mediator)
{}
//声明
void Declare(string message)
{
_mediator->Declare(message, *this);
}
void GetMessage(string message)
{
cout << "伊拉克获得对方信息:" << message << endl;
}
};
//联合国安理事会,具体的中介者类
class UnitedNationsSecurityCouncil : public UnitedNations
{
public:
UnitedNationsSecurityCouncil()
{
colleague1 = new USA(*this);
colleague2 = new Iraq(*this);
}
void Declare(string message, Country& colleague)
{
//如果是美国,则发送给伊拉克,否则发送给美国
if (typeid(colleague) == typeid(USA))
colleague2->GetMessage(message);
else
colleague1->GetMessage(message);
}
~UnitedNationsSecurityCouncil()
{
delete colleague1;
delete colleague2;
}
private:
USA* colleague1;
Iraq* colleague2;
};
int main()
{
UnitedNationsSecurityCouncil UNSC;
USA usa(UNSC);
Iraq Iraq(UNSC);
usa.Declare("不准研制核武器,否则要发动战争!");
Iraq.Declare("我们没有核武器,也不怕侵略");
system("pause");
return 0;
}