中介者模式(Mediator):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地交互引用,从而使耦合松散,而且可以独立地改变它们之间的交互。
四个角色:
- 抽象中介者Mediator
- 具体中介者对象ConcreteMediator
- 抽象类Abstract
- 具体抽象类ConcreteAbstract
中介者模式优点:
- Mediator的出现减少了各个Abstract的耦合,使得可以独立地改变和复用各个Abstract类和Mediator。
- 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更客观的角度去看待系统。
中介者模式缺点:
由于ConcreteMediator控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个ConcreteAbstract都负责。
模式实现:
//前向声明
class Abstract;
//中介者抽象类
class Mediator{
public:
virtual void Send(std::string message, Abstract *abstract){}
};
//抽象类
class Abstract{
protected:
Mediator *mediator;
public:
//构造中介者
Abstract(Mediator *mediator){
this->mediator = mediator;
}
};
//具体抽象类1
class ConcreteAbstract1: public Abstract{
public:
ConcreteAbstract1(Mediator *me):Abstract(me){}
void Send(std::string message){
//中介者送出去
mediator->Send(message, this);
}
void Notify(std::string message){
std::cout << "ConcreteAbstract1 receive message: " << message << " ---(From ConcreteAbstract2)" << std::endl;
}
};
//具体抽象类2
class ConcreteAbstract2: public Abstract{
public:
ConcreteAbstract2(Mediator *me):Abstract(me){}
void Send(std::string message){
//中介者送出去
mediator->Send(message, this);
}
void Notify(std::string message){
std::cout << "ConcreteAbstract2 receive message: " << message << " ---(From ConcreteAbstract1)" << std::endl;
}
};
//具体中介者
class ConcreteMediator: public Mediator{
private:
//需了解所存的具体抽象类对象
ConcreteAbstract1 *CA1;
ConcreteAbstract2 *CA2;
public:
ConcreteMediator(){}
void setConcreteMediator(ConcreteAbstract1 *CA1, ConcreteAbstract2 *CA2){
this->CA1 = CA1;
this->CA2 = CA2;
}
virtual void Send(std::string message, Abstract *abstract){
if(abstract == CA1)
CA2->Notify(message);
else
CA1->Notify(message);
}
};
客户端:
//Client
int main(){
ConcreteMediator *m = new ConcreteMediator;
//具体的抽象这认识具体的中介者
ConcreteAbstract1 *ca1 = new ConcreteAbstract1(m);
ConcreteAbstract2 *ca2 = new ConcreteAbstract2(m);
//让中介者认识两个具体的抽象类
m->setConcreteMediator(ca1, ca2);
ca1->Send("Hello"); //Output: ConcreteAbstract2 receive message: Hello ---(From ConcreteAbstract1)
ca2->Send("Hi"); //Output: ConcreteAbstract1 receive message: Hi ---(From ConcreteAbstract2)
if(m != NULL){
delete m;
m = NULL;
}
if(ca1 != NULL){
delete ca1;
ca1 = NULL;
}
if(ca2 != NULL){
delete ca2;
ca2 = NULL;
}
return 0;
}