前言

尊重原创,本系列文本解析部分主要基于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 模式简介:

   中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。比如中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。

问题:

   在面向对象系统的设计和开发过程中,对象之间的交互和通信是最为常见的情况,因为对象间的交互本身就是一种通信。在系统比较小的时候,可能对象间的通信不是很多、对象也比较少,我们可以直接硬编码到各个对象的方法中。但是当系统规模变大,对象的量变引起系统复杂度的急剧增加,对象间的通信也变得越来越复杂,这时候我们就要提供一个专门处理对象间交互和通信的类,这个中介者就是Mediator模式。Mediator模式提供将对象间的交互和通讯封装在一个类中,各个对象间的通信不必显势去声明和引用,大大降低了系统的复杂性能(了解一个对象总比深入熟悉n个对象要好)。另外Mediator模式还带来了系统对象间的松耦合,这些将在讨论中详细给出。

模式选择

   Mediator模式典型的结构图为:
Mediator Pattern

实现

完整代码示例(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设计中的每个类的职责要单一和集中的原则。