(七)中介者模式-C++实现
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其解耦合松散而且可以独立地改变他们之间的交互。
中介者模式适合于 系统中不希望对象之间直接交互,即不希望类之间相互包含,成为朋友。
中介者模式中有四种角色:
(1)中介者:定义了用于同事之间通信的方法
(2)具体中介者:如果只有一个中介者,那么可以只有一个具体中介者,不需要抽象中介者。它包含具体同事的引用,实现他们之间的通信。
(3)同事:抽象类,规定一些方法
(4)具体同事:包含具体中介者的引用,一个具体同事需要和其他同事交互时,将自己的请求通知给他包含的具体中介者即可。
在本例子中,同事A分别需要通知B和C一些消息,而B也需要通知A和C一些消息,同样,C也需要通知A和B一些消息。利用中介者模式实现如下:
(1)Colleague.h
1 #ifndef _COLLEAGUE_H_ 2 #define _COLLEAGUE_H_ 3 #include <string> 4 #include <iostream> 5 #include "Mediator.h" 6 using namespace std; 7 class ConcreteMediator; 8 9 //中介者模式 10 //抽象同事和具体同事的定义 如果没有中介者 他们需要相互包含 11 class Colleague{ 12 public: 13 virtual void giveMess(string mess[]) = 0; 14 virtual void receiverMess(string mess) = 0; 15 virtual void setName(string name) = 0; 16 virtual string getName() = 0; 17 18 }; 19 20 //具体同事 21 class ColleagueA : public Colleague{ 22 public: 23 ColleagueA(ConcreteMediator *mediator); 24 void setName(string name) override; 25 string getName() override; 26 void giveMess(string mess[]) override; 27 void receiverMess(string name) override; 28 29 private: 30 ConcreteMediator *myMediator; 31 string name; 32 33 }; 34 35 36 class ColleagueB : public Colleague{ 37 public: 38 ColleagueB(ConcreteMediator *mediator); 39 void setName(string name) override; 40 string getName() override; 41 void giveMess(string mess[]) override; 42 void receiverMess(string name) override; 43 44 private: 45 ConcreteMediator *myMediator; 46 string name; 47 48 }; 49 50 class ColleagueC : public Colleague{ 51 public: 52 ColleagueC(ConcreteMediator *mediator); 53 void setName(string name) override; 54 string getName() override; 55 void giveMess(string mess[]) override; 56 void receiverMess(string name) override; 57 58 private: 59 ConcreteMediator *myMediator; 60 string name; 61 62 }; 63 64 65 #endif
(2)Colleague.cpp
1 #include "Colleague.h" 2 3 ColleagueA::ColleagueA(ConcreteMediator *mediator) 4 { 5 this->myMediator = mediator; 6 myMediator->registerColleagueA(this); 7 } 8 9 void ColleagueA::setName(string name) 10 { 11 this->name = name; 12 } 13 14 string ColleagueA::getName() 15 { 16 return name; 17 } 18 19 void ColleagueA::giveMess(string mess[]) 20 { 21 //由中介者将消息传递给其同事 22 myMediator->deliverMess(this, mess); 23 } 24 25 void ColleagueA::receiverMess(string mess) 26 { 27 cout << name << " get message: " << mess << endl; 28 } 29 30 ColleagueB::ColleagueB(ConcreteMediator *mediator) 31 { 32 this->myMediator = mediator; 33 myMediator->registerColleagueB(this); 34 } 35 36 void ColleagueB::setName(string name) 37 { 38 this->name = name; 39 } 40 41 string ColleagueB::getName() 42 { 43 return name; 44 } 45 46 void ColleagueB::giveMess(string mess[]) 47 { 48 //由中介者将消息传递给其同事 49 myMediator->deliverMess(this, mess); 50 } 51 52 void ColleagueB::receiverMess(string mess) 53 { 54 cout << name << " get message: " << mess << endl; 55 } 56 57 ColleagueC::ColleagueC(ConcreteMediator *mediator) 58 { 59 this->myMediator = mediator; 60 myMediator->registerColleagueC(this); 61 } 62 63 void ColleagueC::setName(string name) 64 { 65 this->name = name; 66 } 67 68 string ColleagueC::getName() 69 { 70 return name; 71 } 72 73 void ColleagueC::giveMess(string mess[]) 74 { 75 //由中介者将消息传递给其同事 76 myMediator->deliverMess(this, mess); 77 } 78 79 void ColleagueC::receiverMess(string mess) 80 { 81 cout << name << " get message: " << mess << endl; 82 }
(3)Mediator.h
1 #ifndef _MEDIATOR_H_ 2 #define _MEDIATOR_H_ 3 #include "Colleague.h" 4 #include <string> 5 using namespace std; 6 7 class Colleague; 8 class ColleagueA; 9 class ColleagueB; 10 class ColleagueC; 11 12 13 //中介者 由于本例子中只有一个中介者 所以只定义一个具体中介者 14 15 class ConcreteMediator{ 16 public: 17 void registerColleagueA(ColleagueA *ca); 18 void registerColleagueB(ColleagueB *cb); 19 void registerColleagueC(ColleagueC *cc); 20 21 void deliverMess(Colleague *colleague, string mess[]); 22 23 private: 24 ColleagueA *ca; 25 ColleagueB *cb; 26 ColleagueC *cc; 27 }; 28 29 #endif
(4)Mediator.cpp
1 #include "Mediator.h" 2 3 void ConcreteMediator::registerColleagueA(ColleagueA *ca) 4 { 5 this->ca = ca; 6 } 7 8 void ConcreteMediator::registerColleagueB(ColleagueB *cb) 9 { 10 this->cb = cb; 11 } 12 13 void ConcreteMediator::registerColleagueC(ColleagueC *cc) 14 { 15 this->cc = cc; 16 } 17 18 void ConcreteMediator::deliverMess(Colleague *colleague, string mess[])//如果这里需要判断mess的长度,需要将其作为参数传递进来 19 { 20 if (typeid(*colleague) == typeid(*ca)) 21 { 22 //通知其他的同事 23 cb->receiverMess(colleague->getName() + mess[0]); 24 cc->receiverMess(colleague->getName() + mess[1]); 25 } 26 else if (typeid(*colleague) == typeid(*cb)) 27 { 28 ca->receiverMess(colleague->getName() + mess[0]); 29 cc->receiverMess(colleague->getName() + mess[1]); 30 } 31 else if (typeid(*colleague) == typeid(*cc)) 32 { 33 ca->receiverMess(colleague->getName() + mess[0]); 34 cb->receiverMess(colleague->getName() + mess[1]); 35 } 36 }
(5)MediatorMain.cpp
1 #include "Colleague.h" 2 #include "Mediator.h" 3 4 5 int main() 6 { 7 ConcreteMediator *mediator = new ConcreteMediator(); 8 9 ColleagueA *ca = new ColleagueA(mediator); 10 ColleagueB *cb = new ColleagueB(mediator); 11 ColleagueC *cc = new ColleagueC(mediator); 12 13 ca->setName("国A"); 14 cb->setName("国B"); 15 cc->setName("国C"); 16 17 string messA[] = { "要求归还100斤土豆", "要求归还20头牛" }; 18 ca->giveMess(messA); 19 cout << endl; 20 string messB[] = { "要求归还10只鸡", "要求归还15匹马" }; 21 cb->giveMess(messB); 22 cout << endl; 23 string messC[] = { "要求归还300斤小麦", "要求归还50头驴" }; 24 cc->giveMess(messC); 25 26 return 0; 27 }
需要注意的是,在中介者中传递消息的时候需要判断当前参数中指向的对象是哪种类型,用到了操作符typeid。它的参数类型是对象,若两个对象是同一个类型则返回true。
中介者模式适合于一个对象需要引用很多其他对象,或者是对象之间的相互引用比较多的情况。
优点也有很多,比如:
(1)将分布于多个对象之间的交互行为集中在一起。
(2)使得各个具体同事之间完全解耦。
等。