目录
在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。
我想到了生活中的中介。有人有房子想出租(房东),但是他不想自己去找那些想租房子的人(租客),也不想保存那些想租房子的人的信息。而有些人想租房子(租客),但不知道哪些房源出租,也不想自己存房源的信息。那上面这两类人怎么办呢?他们可以找中介。这就变成了 房东-中介-租客 之间的关系。这样一来房东就不需要有租客的信息,也能将房子租出去,而租客也不需要房东的信息,也能找到房子,中介成了房东和租客之间的纽带。而中介其实什么都没有,他的职能就是为房东们寻找合适的租客,替租客们匹配合适的房子。
![](https://i-blog.csdnimg.cn/blog_migrate/e834ec8515658abede8f2e037d6a3072.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3d19e2c66313df55fa2e3d0a4cec6207.png)
好的,我们通过中介的存在,切断了房东与租客之间的联系,从而解决了房东和租客们的难题。这样刚好符合设计模式中的迪米特原则,这个原则所说的就是要尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。 我们为了减少对象之间的交互和耦合,符合迪米特原则,那么就可以使用中介者模式,先来学习下中介者模式的定义。
定义
中介者模式(调停者模式,属于行为型设计模式):
- 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- 抽象中介者(Mediator)角色:定义了同事对象到中介者对象的接口,提供了同事对象注册与发送同事对象信息的抽象方法。主要用于各个同事对象之间的通信。
- 具体中介者(ConcreteMediator)角色:继承于抽象中介者,实现了父类定义的方法。具体中介者需要包含所有具体同事的引用,并通过实现中介者接口中的方法来满足具体同事之间的通信请求。
- 抽象同事类(Colleague)角色:保存了中介者对象引用,只与中介者交互,不与其他同时对象交互
- 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
这里说的同事类就像我们前面所述的 租客,
下面用C++ 代码实现大话设计模式本章代码:
class UnitedNations;
//Colleague 类
class Country
{
protected:
UnitedNations* m_mediator;
public:
explicit Country(UnitedNations* mediator) :m_mediator(mediator) {}
virtual ~Country() = default;
virtual void Declare(string message) = 0;
virtual void GetMessage(string message) = 0;
};
//Mediator
class UnitedNations
{
public:
virtual ~UnitedNations() = default;
virtual void setColleague1(Country* c) = 0;
virtual void setColleague2(Country* c) = 0;
virtual void Declare(string message, Country* colleague) = 0;
};
//ConcreteMediator
class UnitedNationsSecurityCouncil :public UnitedNations
{
private:
Country* colleague1 = nullptr;
Country* colleague2 = nullptr;
public:
void setColleague1(Country* c)override;
void setColleague2(Country* c)override;
void Declare(string message, Country* colleague)override;
};
void UnitedNationsSecurityCouncil::setColleague1(Country* c)
{
colleague1 = c;
}
void UnitedNationsSecurityCouncil::setColleague2(Country* c)
{
colleague2 = c;
}
void UnitedNationsSecurityCouncil::Declare(string message, Country* colleague)
{
if (colleague == colleague1)
colleague2->GetMessage(message);
else
colleague1->GetMessage(message);
}
//ConcreteColleague
class USA :public Country
{
public:
explicit USA(UnitedNations* mediator) :Country(mediator) {}
void Declare(string message)override;
void GetMessage(string message)override;
};
//ConcreteColleague
class Iraq :public Country
{
public:
explicit Iraq(UnitedNations* mediator) :Country(mediator) {}
void Declare(string message)override;
void GetMessage(string message)override;
};
void USA::Declare(string message)
{
m_mediator->Declare(message, this);
}
void USA::GetMessage(string message)
{
cout << "美国获得对方信息:" << message << endl;
}
void Iraq::Declare(string message)
{
m_mediator->Declare(message, this);
}
void Iraq::GetMessage(string message)
{
cout << "伊拉克获得对方信息:" << message << endl;
}
int main()
{
UnitedNationsSecurityCouncil UNSC;
USA c1(&UNSC);
Iraq c2(&UNSC);
UNSC.setColleague1(&c1);
UNSC.setColleague2(&c2);
c1.Declare("不准研制核武器,否则要发动战争!");
c1.Declare("我们没有核武器,也不怕侵略。");
system("pause");
return 0;
}
优点
- Mediator类 的出现减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague,这样 Colleague之间可以相对独立地使用。
- 将对象间的一对多关联 转变 为一对一的关联,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合。这样提高系统的灵活性,使得系统易于维护和扩展。
- 使用中介者模式可以将对象的行为和协作进行抽象,能够比较灵活的处理对象间的相互作用。
缺点
- 由于中介者对象封装了系统中对象之间的交互,当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,维护难度会逐渐增大
应用场景
- 当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时涉及很多其他对象的行为,可使用中介者模式
在面向对象编程中,一个类必然会与其他的类发生依赖关系,完全独立的类是没有意义的。一个类同时依赖多个类的情况也相当普遍,既然存在这样的情况,说明,一对多的依赖关系有它的合理性,适当的使用中介者模式可以使原本凌乱的对象关系清晰,但是如果滥用,则可能会带来反的效果。一般来说,只有对于那种同事类之间是网状结构的关系,才会考虑使用中介者模式。可以将网状结构变为星状结构,使同事类之间的关系变的清晰一些。
中介者模式是一种比较常用的模式,也是一种比较容易被滥用的模式。对于大多数的情况,同事类之间的关系不会复杂到混乱不堪的网状结构,因此,大多数情况下,将对象间的依赖关系封装的同事类内部就可以的,没有必要非引入中介者模式。滥用中介者模式,只会让事情变的更复杂。
代理模式、外观模式和中介者模式对比
当我们学完中介者模式是不是会觉得和此前讲过的代理模式和外观模式有些类似呢?现在我们一一来将它们进行对比。
代理模式和中介者模式
- 代理模式是结构型设计模式,它有很多种类型,主要是在访问对象时引入一定程度的间接性,由于有间接性,就可以附加多种的用途,比如进行权限控制。中介者模式则是为了减少对象之间的相互耦合。虽然网上有很多代理模式和中介者模式的对比,但是在我看来这两者实际上并没有可比性,只是看起来有些类似罢了。
外观模式和中介者模式
外观模式主要是以封装和隔离为主要任务,中介者则是调停同事类之间的关系,因此,中介者具有部分业务的逻辑控制。主要区别为:
- - 外观模式的子系统如果脱离外观模式还是可以运行的,而中介者模式增加了业务逻辑,同事类不能脱离中介者而独自存在。
- - 外观模式中,子系统是不知道外观类的存在的,而中介者模式中,每个同事类都知道中介者。
- - 外观模式将子系统的逻辑隐藏,用户不知道子系统的存在,而中介者模式中,用户知道同事类的存在。