Mediator:中介者模式,当多个对象彼此间都有联系的时候,我们就可以应用Mediator将对象间的多对多关系转换为
一对多的关系,这样做,可以使各个对象间的耦合松散。统一管理对象间的通信协议。但也可能使得Mediator对象
成为一个系统中的庞然大物,难以维护。
好,我们现在来看一个实例。下面有三个对象:A,B,C。他们之间的关系是相互的,每个对象都知道其余的两个对象,都可以和其余的对象打交道。
我们先看看不使用Mediator模式的代码,这样的代码可能会产生混乱。
// A.H 类A 的头文件,下面的类B和类C的结构相同,只是为了演示出三个类之间“纠缠不清”的关系
#define _A_H
class B;
class C;
class A
... {
public:
void SetColleage(B *b, C *c); // 设置同事(协助者),也就是需要打交道的对象
void ACallB(); // 调用协助者B的服务
void ACallC(); // 调用协助者C的服务
void Function(); // 自己本身的服务
private:
B *_b;
C *_c;
} ;
#endif
// A.CPP
#include " b.h "
#include " c.h "
#include < iostream >
using namespace std;
void A::SetColleage(B * b, C * c)
... {
_b = b;
_c = c;
}
void A::ACallB()
... {
cout << "A call ";
_b->Function();
}
void A::ACallC()
... {
cout << "A call ";
_c->Function();
}
void A::Function()
... {
cout << "A's Func!" << endl;
}
下面的B.H、B.CPP、C.H、C.CPP都和上面两个文件相似,下面给出这4个文件的完整内容
// B.H
#define _B_H
class A;
class C;
class B
... {
public:
void SetColleage(A *a, C *c);
void BCallA();
void BCallC();
void Function();
private:
A *_a;
C *_c;
} ;
#endif
// B.CPP
#include " b.h "
#include " c.h "
#include < iostream >
using namespace std;
void B::SetColleage(A * a, C * c)
... {
_a = a;
_c = c;
}
void B::BCallA()
... {
cout << "B call ";
_a->Function();
}
void B::BCallC()
... {
cout << "B call ";
_c->Function();
}
void B::Function()
... {
cout << "B's Func!" << endl;
}
// C.H
#define _C_H
class A;
class B;
class C
... {
public:
void SetColleage(A *a, B *b);
void CCallA();
void CCallB();
void Function();
private:
A *_a;
B *_b;
} ;
#endif
// C.CPP
#include " b.h "
#include " c.h "
#include < iostream >
using namespace std;
void C::SetColleage(A * a, B * b)
... {
_a = a;
_b = b;
}
void C::CCallA()
... {
cout << "C call ";
_a->Function();
}
void C::CCallB()
... {
cout << "C call ";
_b->Function();
}
void C::Function()
... {
cout << "C's Func!" << endl;
}
从上面三个类可以看出来,他们之间彼此都有关系,都可以和另外两个类对象打交道。在现实的软件系统中也可能会出现这种情况,整个系统的类间都有耦合性,最终导致整个系统变成一个耦合性很强的系统,完全没有重用可言。由于这种弊端,我们可以运用Mediator模式来解耦,这属于下篇文章的内容,现在我们先来看看怎么调用上面的这些类。
// main.CPP
using namespace std;
#include " a.h "
#include " b.h "
#include " c.h "
void main()
... {
A a;
B b;
C c;
a.SetColleage(&b, &c);
b.SetColleage(&a, &c);
c.SetColleage(&a, &b);
a.ACallB();
a.ACallC();
b.BCallA();
b.BCallC();
c.CCallA();
c.CCallB();
}
好了,从这个调用可以看出来,他们之间的耦合性非常强,这里只是三个对象,而且调用的方式比较统一(因为是例子程序),我们还能把他们的关系给搞清楚,但在现实的软件开发中,往往类间的关系比这里的复杂多了,这个时候我们就要“剪”断这些错乱的关系,而“剪刀”就是Mediator模式。
好了,从这个调用可以看出来,他们之间的耦合性非常强,这里只是三个对象,而且调用的方式比较统一(因为是例子程序),我们还能把 他们的关系给搞清楚,但在现实的软件开发中,往往类间的关系比这里的复杂多了,这个时候我们就要“剪”断这些错乱的关系,而“剪刀”就是Mediator 模式。
上一篇用一个例子程序来说明程序中可能会出现的类间关系过于复杂,而导致程序的结构变差的情况。这一章的目的就是说明如何使用Mediator模式来解决这个问题。
在 看实际的代码之前,我们先了解一下为什么Mediator模式能够解决这些问题。问题的所在就是类之间被互相引用而导致混乱,这显然就是多对多的关系(这 就是Mediator使用的语境),我们要解决混乱,就要把他们的关系简化为一对多的关系。充当这个角色的就是Mediator。就好象一班人在打架,你 打我,我打你,场面十分混乱,这个时候出来一个人为他们做调解,这个人就是我们的Mediator了。:)
好了,我们首先在程序中写一个Mediator的类:
// Mediator.H
#define _MEDIATOR_H
class A;
class B;
class C;
class Mediator
... {
public:
Mediator(A *a, B *b, C *c);
void ACallB();
void ACallC();
void BCallA();
void BCallC();
void CCallA();
void CCallB();
private:
A *_a;
B *_b;
C *_c;
} ;
#endif
// Mediator.CPP
我们看到,main() 函数写在 Mediator.CPP 中, 里面的调用基本上和上一篇的调用一样,唯一不同的是多了Mediator对象的加入。a、b、c 三个对象也不需要设置两个协助者了,只需要设置一个Mediator就行了,而调用和上篇完全一样(当然在内部实现是不一样的,但在接口的看来,它们是没 什么变化的),这样就把三个类之间复杂的关系解开了。
我们再看看其他三个类的变化,先看看类A,其余两个是差不多的。
// A.H
// A.CPP
using namespace std;
#include " a.h "
#include " b.h "
#include " c.h "
#include " Mediator.h "
Mediator::Mediator(A * a, B * b, C * c)
... {
_a = a;
_b = b;
_c = c;
}
void Mediator::ACallB()
... {
cout << "A call ";
_b->Function();
}
void Mediator::ACallC()
... {
cout << "A call ";
_c->Function();
}
void Mediator::BCallA()
... {
cout << "B call ";
_a->Function();
}
void Mediator::BCallC()
... {
cout << "B call ";
_c->Function();
}
void Mediator::CCallA()
... {
cout << "C call ";
_a->Function();
}
void Mediator::CCallB()
... {
cout << "C call ";
_b->Function();
}
void main()
... {
A a;
B b;
C c;
Mediator m(&a, &b, &c);
a.SetMediator(&m);
b.SetMediator(&m);
c.SetMediator(&m);
a.ACallB();
a.ACallC();
b.BCallA();
b.BCallC();
c.CCallA();
c.CCallB();
}
#define _A_H
class B;
class C;
class Mediator;
class A
... {
public:
void SetMediator(Mediator *m);
void ACallB();
void ACallC();
void Function();
private:
B *_b;
C *_c;
Mediator *_m;
} ;
#endif
#include " b.h "
#include " c.h "
#include " Mediator.h "
#include < iostream >
using namespace std;
void A::SetMediator(Mediator * m)
... {
_m = m;
}
void A::ACallB()
... {
_m->ACallB();
}
void A::ACallC()
... {
_m->ACallC();
}
void A::Function()
... {
cout << "A's Func!" << endl;
}
可以看看类A中原来调用其他类的服务,现在都变成了调用 Mediator 中的服务了,再看看 Mediator 的实现,就应该会明白这个模式的思想所在了。
下面再看看其他两个类的实现:
// B.H
#define _B_H
class A;
class C;
class Mediator;
class B
... {
public:
void SetMediator(Mediator *m);
void BCallA();
void BCallC();
void Function();
private:
A *_a;
C *_c;
Mediator *_m;
} ;
#endif
// B.CPP
#include " b.h "
#include " c.h "
#include " Mediator.h "
#include < iostream >
using namespace std;
void B::SetMediator(Mediator * m)
... {
_m = m;
}
void B::BCallA()
... {
_m->BCallA();
}
void B::BCallC()
... {
_m->BCallC();
}
void B::Function()
... {
cout << "B's Func!" << endl;
}
// C.H
#define _C_H
class A;
class B;
class Mediator;
class C
... {
public:
void SetMediator(Mediator *m);
void CCallA();
void CCallB();
void Function();
private:
A *_a;
B *_b;
Mediator *_m;
} ;
#endif
// C.CPP
#include " b.h "
#include " c.h "
#include " Mediator.h "
#include < iostream >
using namespace std;
void C::SetMediator(Mediator * m)
... {
_m = m;
}
void C::CCallA()
... {
_m->CCallA();
}
void C::CCallB()
... {
_m->CCallB();
}
void C::Function()
... {
cout << "C's Func!" << endl;
}
我们可以看到,一二两篇代码的执行结果完全相同,但使用了Mediator模式之后,原来在各个对象 内部所做的事情,现在全部移交到Mediator里了。也就是将分布在各个对象里面的协议处理过程,全部统一放在Mediator里去做了。骤看来,好像 我们是把职责转移了,但是对于代码逻辑的清晰却有很大的好处,这个模式让我们能专注于各个对象之间的交互(他们的交互都放在Mediator类里去做 了)。
我们还可以看出,Mediator的核心思想就是把错综复杂的类间的关系独立出来,使得他们的关系清晰化。这样做的
好处是如果类间的交互协议有变化,则只修改Mediator类就行了,但是它的缺点也在于Mediator类,因为所有的
交互都转移到Mediator中,他的复杂性可想而知,搞不好会变成一个庞然大物,难以维护。
这里还是希望大家能动手实现一下,由于关系有点乱,没办法做到傻瓜式的简单。我考虑过如果使用两个
对象来演示又太简单,收不到应有的效果,使用三个对象又会很难描述,所以还是希望大家仿照这两个例子,
动手实现一下,只要你在机器上编完这两个例子(或者你自己突发奇想的例子),然后再思考一下,一定会对Mediator模式有个清晰的认识!