中介者模式(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;
}