中介者模式
理论
尽管将一个系统分割成许多对象通常可以增加其复用性,但是对象间相互连接的激增又会降低其复用性。大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体。所以对系统的行为进行任何较大的改动就十分困难。
根据迪米特法则,可以通过中介者对象将系统的网状结构变成以中介者为中心的星形结构,每个具体对象由中介者对象设计,使系统的结构不会因新对象的引入造成大量的修改工作。
中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
中介者模式的优点:
1. 减少了各个 Colleague 的耦合,使得可以独立地改变和复用各个 Colleague 类和 Mediator
2. 由于把对象如何协作进行了抽象,将中介作为一个独立地概念并将其封装在一个对象中,这样关注地对象就从对象各自本身地行为转移到它们之间地交互上来,也就是站在一个更宏观地角度去看待系统。
中介者模式地缺点:
由于 ConcreteMediator 控制了集中化,于是就把交互复杂性变为了中介者地复杂性,这就使得中介者会变得比任何一个 ConcreteColleague 都复杂。
中介者模式地应用场景:
1. 应用于一组对象以定义良好但是复杂地方式进行通信地场合
2. 想要定制一个分布在多个类中的行为,而又不想生成太多的子类的场合
实例
模拟各个国家通过联合进行通信,联合国知道各个国家。国与国之间通过联合国这个中介者来发生关系,而不用直接通信。
UML类图
代码实现
#include <iostream> using namespace std; class Country; //联合国机构类 class UnitedNations { public: //声明 virtual void Declare(string message, Country* colleague) = 0; }; //国家类 class Country{ public: Country(UnitedNations* mediator){ this->mediator = mediator; } protected: UnitedNations* mediator; }; //美国 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; } }; //伊拉克 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 UnitedNationsSC :public UnitedNations{ public: void Declare(string message, Country* colleague) { if (colleague == colleague1) { colleague2->GetMessage(message); } else { colleague1->GetMessage(message); } } void Colleague1(USA* usa) { this->colleague1 = usa; } void Colleague2(Iraq* iraq) { this->colleague2 = iraq; } private: USA* colleague1; Iraq* colleague2; }; int main() { UnitedNationsSC* UNSC = new UnitedNationsSC(); USA* c1 = new USA(UNSC); Iraq* c2 = new Iraq(UNSC); UNSC->Colleague1(c1); UNSC->Colleague2(c2); c1->Declare("不准研制核武器,否则发动战争!"); c2->Declare("我们没有核武器,也不怕侵略。"); delete UNSC; UNSC = nullptr; delete c1; c1 = nullptr; delete c2; c2 = nullptr; return 0; }
运行结果: