前言
尊重原创,本系列文本解析部分主要基于Candidate for Master’s Degree School of Computer Wuhan University的K_Eckel([email protected] )《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》。为了避免重造轮子,本系列博文对源码在ubuntu16.04下做了验证并上传到了gitee ,再次感谢。
如有问题,可邮件联系我([email protected] )并共同探讨解决方案。
目录
创建型模式(Creating Pattern)
Factory 模式 | AbstactFactory 模式 | Singleton 模式 | Builder 模式 | Prototype 模式
结构型模式(Structrual Pattern)
Bridge 模式 | Adapter 模式 | Decorator 模式 | Composite 模式 | Flyweight 模式 | Facade 模式 | Proxy 模式
行为型模式(Behavioral Pattern)
Template 模式 | Strategy 模式 | State 模式 | Observer 模式 | Memento 模式 | Mediator 模式 | Command 模式 | Visitor 模式 | Iterator 模式 | Interpreter 模式 | Chain of Responsibility 模式
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。比如中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。
问题:
在面向对象系统的设计和开发过程中,对象之间的交互和通信是最为常见的情况,因为对象间的交互本身就是一种通信。在系统比较小的时候,可能对象间的通信不是很多、对象也比较少,我们可以直接硬编码到各个对象的方法中。但是当系统规模变大,对象的量变引起系统复杂度的急剧增加,对象间的通信也变得越来越复杂,这时候我们就要提供一个专门处理对象间交互和通信的类,这个中介者就是Mediator模式。Mediator模式提供将对象间的交互和通讯封装在一个类中,各个对象间的通信不必显势去声明和引用,大大降低了系统的复杂性能(了解一个对象总比深入熟悉n个对象要好)。另外Mediator模式还带来了系统对象间的松耦合,这些将在讨论中详细给出。
模式选择
Mediator模式典型的结构图为:
实现
完整代码示例(code)
Mediator模式实现不是很困难,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用 C++实现,并在 Visual Studio Code,Version: 1.36.1 下测试运行)。
源码gitee地址:点击这里
代码目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\behavioralPattern\Mediator> tree /F 卷 Windows 的文件夹 PATH 列表 卷序列号为 F0C5-AFA6 C:. ├─include │ Colleage.h │ Mediator.h │ └─src a.out Colleage.cpp main.cpp Mediator.cpp PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\behavioralPattern\Mediator>
Colleage.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 // Colleage.h #ifndef _COLLEAGE_H_ #define _COLLEAGE_H_ #include <string> using namespace std; class Mediator; class Colleage { private: /* data */ protected: Colleage(/* args */); Colleage(Mediator* mdt); Mediator* _mdt; public: virtual ~Colleage(); virtual void Aciton() = 0; virtual void SetState(const string& sdt) = 0; virtual string GetState() = 0; }; class ConcreteColleageA : public Colleage { private: string _sdt; public: ConcreteColleageA(/* args */); ConcreteColleageA(Mediator* mdt); ~ConcreteColleageA(); void Aciton(); void SetState(const string& sdt); string GetState(); }; class ConcreteColleageB : public Colleage { private: string _sdt; public: ConcreteColleageB(/* args */); ConcreteColleageB(Mediator* mdt); ~ConcreteColleageB(); void Aciton(); void SetState(const string& sdt); string GetState(); }; #endif //~_COLLEAGE_H_
Mediator.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 // Mediator.h #ifndef _MEDIATOR_H_ #define _MEDIATOR_H_ class Colleage; class Mediator { private: /* data */ protected: Mediator(/* args */); public: virtual ~Mediator(); virtual void DoActionFromAtoB() = 0; virtual void DoActionFromBtoA() = 0; }; class ConcreteMediator:public Mediator { private: Colleage* _clgA; Colleage* _clgB; public: ConcreteMediator(/* args */); ConcreteMediator(Colleage*clgA,Colleage* clgB); ~ConcreteMediator(); void SetConcreteColleageA(Colleage*clgA); void SetConcreteColleageB(Colleage*clgB); Colleage* GetConcreteColleageA(); Colleage* GetConcreteColleageB(); void IntroColleage(Colleage*clgA,Colleage* clgB); void DoActionFromAtoB(); void DoActionFromBtoA(); }; #endif //~_MEDIATOR_H
Colleage.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // Colleage.cpp #include "../include/Colleage.h" #include <iostream> #include "../include/Mediator.h" using namespace std; Colleage::Colleage(/* args */) {} Colleage::~Colleage() {} Colleage::Colleage(Mediator* mdt) { this->_mdt = mdt; } ConcreteColleageA::ConcreteColleageA(/* args */) {} ConcreteColleageA::~ConcreteColleageA() {} ConcreteColleageA::ConcreteColleageA(Mediator* mdt) : Colleage(mdt) {} string ConcreteColleageA::GetState() { return _sdt; } void ConcreteColleageA::SetState(const string& sdt){_sdt = sdt;} void ConcreteColleageA::Aciton(){ _mdt->DoActionFromAtoB(); cout<<"State of ConcreteColleageB:"<<""<<this->GetState()<<endl; } ConcreteColleageB::ConcreteColleageB(/* args */) {} ConcreteColleageB::~ConcreteColleageB() {} ConcreteColleageB::ConcreteColleageB(Mediator* mdt) : Colleage(mdt) {} string ConcreteColleageB::GetState() { return _sdt; } void ConcreteColleageB::SetState(const string& sdt){_sdt = sdt;} void ConcreteColleageB::Aciton(){ _mdt->DoActionFromBtoA(); cout<<"State of ConcreteColleageB:"<<""<<this->GetState()<<endl; }
Mediator.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // Mediator.cpp #include "../include/Mediator.h" #include "../include/Colleage.h" Mediator::Mediator(/* args */) {} Mediator::~Mediator() {} ConcreteMediator::ConcreteMediator(/* args */) {} ConcreteMediator::~ConcreteMediator() {} ConcreteMediator::ConcreteMediator(Colleage* clgA,Colleage* clgB){ this->_clgA = clgA; this->_clgB = clgB; } void ConcreteMediator::DoActionFromAtoB(){ _clgB->SetState(_clgA->GetState()); } void ConcreteMediator::SetConcreteColleageA(Colleage* clgA){ this->_clgA = clgA; } void ConcreteMediator::SetConcreteColleageB(Colleage* clgB){ this->_clgB = clgB; } Colleage* ConcreteMediator::GetConcreteColleageA(){ return _clgA; } Colleage* ConcreteMediator::GetConcreteColleageB(){ return _clgB; } void ConcreteMediator::IntroColleage(Colleage*clgA,Colleage* clgB){ this->_clgA = clgA; this->_clgB = clgB; } void ConcreteMediator::DoActionFromBtoA(){ _clgA->SetState(_clgB->GetState()); }
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // main.cpp #include <iostream> #include "../include/Colleage.h" #include "../include/Mediator.h" using namespace std; int main(int argc, char* argv[]) { ConcreteMediator* m = new ConcreteMediator(); ConcreteColleageA* c1 = new ConcreteColleageA(m); ConcreteColleageB* c2 = new ConcreteColleageB(m); m->IntroColleage(c1, c2); c1->SetState("old"); c2->SetState("old"); c1->Aciton(); c2->Aciton(); cout << endl; c1->SetState("new"); c1->Aciton(); c2->Aciton(); cout << endl; c2->SetState("old"); c2->Aciton(); c1->Aciton(); return 0; }
代码说明
Mediator模式的实现关键就是将对象Colleague
之间的通信封装到一个类种单独处理,为了模拟Mediator模式的功能,这里给每个Colleague
对象一个string
型别以记录其状态,并通过状态改变来演示对象之间的交互和通信。这里主要就Mediator
的示例运行结果给出分析:
将ConcreteColleageA
对象设置状态“old
”,ConcreteColleageB
也设置状态“old
”;
ConcreteColleageA
对象改变状态,并在Action中和ConcreteColleageB
对象进行通信,并改变ConcreteColleageB
对象的状态为“new
”;
ConcreteColleageB
对象改变状态,并在Action
中和ConcreteColleageA
对象进行通信,并改变ConcreteColleageA
对象的状态为“new
”;
注意到,两个Colleague
对象并不知道它交互的对象,并且也不是显示地处理交互过程,这一切都是通过Mediator
对象完成的,示例程序运行的结果也正是证明了这一点。
编译运行结果:
1 2 3 4 5 6 7 8 9 10 11 PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\behavioralPattern\Mediator\src> g++ *.cpp -std=c++11 PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\behavioralPattern\Mediator\src> .\a.exe State of ConcreteColleageB:old State of ConcreteColleageB:old State of ConcreteColleageB:new State of ConcreteColleageB:new State of ConcreteColleageB:old State of ConcreteColleageB:old PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\behavioralPattern\Mediator\src>
讨论
Mediator模式是一种很有用并且很常用的模式,它通过将对象间的通信封装到一个类中,将多对多的通信转化为一对多的通信,降低了系统的复杂性。Mediator
还获得系统解耦的特性,通过Mediator
,各个Colleague
就不必维护各自通信的对象和通信协议,降低了系统的耦合性,Mediator
和各个Colleague
就可以相互独立地修改了。
Mediator模式还有一个很显著额特点就是将控制集中,集中的优点就是便于管理,也正式符合了OO设计中的每个类的职责要单一和集中的原则。