1. Definition of mediator pattern
Write on the front: The intermediary model has made me understand for a long time, because it is very close to our life, because the so-called "intermediary" blossoms everywhere in our daily life, but it is also true. When I want to combine some examples of this model in life, I found that the details really need to be more speculative.
_Mediator mode, which is traditionally defined as encapsulating a series of object interactions with a mediator object, makes the objects do not need to show mutual reference, thus reducing coupling, and can independently change the interaction between them.
But generally speaking, this model is the various intermediaries we usually see (buying a house, looking for a job, etc.). Here we take looking for a job as an example. Customers provide their own basic information, as well as their goals related positions, salaries and other information; companies provide their own required position information and required skills and other information, intermediaries are responsible for integrating customer information into a database, the company's recruitment information into a database, so that whenever new companies/customers enter the database, they can through intermediaries. Internally, they match the positions/talents that they need from each other. That is to say, the intermediary pattern is a pattern that gathers the needs of customers / companies to form two libraries, and then finds the best matching pattern in these two limited libraries.
Finally, it is worth mentioning that the matching process between objects of multiple classes is often needed in the mediator model. The reason why the mediator model is chosen is that it can transform the complex multi-to-many relationship between different classes into one-to-one relationship, which only needs to contact the mediator class. At the same time, because the complex relationships between classes are handed over to the mediator, the structure of the mediator class will be quite complex and not easy to change.
2. Class diagrams of mediator patterns
_With regard to this class diagram, it is worth mentioning that the one-way relationship between Concrete Mediator specific mediator and Concrete Collegue specific user represents that the specific mediator knows each specific user and uses it as its internal idiom variable. Most of the design patterns studied before are oriented to abstract classes, and most of the member variables used are member variables in abstract classes. However, the abnormal relationship between the concrete classes of the two abstract classes is found here.
Each of these classes is understood in detail as follows:
- Mediator mediator class: This is an abstract class that defines all the interfaces required by the Collegue user class to the mediator object. It may exist in many ways, and the corresponding interfaces for each implementation are different.
- Collegue user class: This is an abstract class, which contains all Mediator mediator classes that need to be used as member variables, and defines the interfaces that specific user classes need to implement (mostly for the reading of user information, and for the use of Mediator mediator classes);
- ConcreteCollegue Specific User Class: This is an instance class of Collegue User Class. It may exist in many different ways, representing different types of users. The basic information between different users is the same (inherited from the parent class), but there may be different unique information, and the use of Mediator intermediaries may also be different.
(Each ConcreteCollegue specific user class only knows its own behavior, and only knows the mediator class, not the existence of other ConcreteCollegue specific user classes) - ConcreteMediator Specific Mediator Class: This is an instance class of Mediator Mediator Mediator Class, which may exist in many different ways, corresponding to the implementation of different mediator functions. It has all the member variables of ConcreteCollegue specific user classes (that is, it needs to know all ConcreteCollegue specific user class objects), and its internal functions (inherited f) ROM The function interface of the parent class) need to rely on these ConcreteCollegue specific user classes for operation.
(When a ConcreteCollegue specific user class calls the ConcreteMediator specific mediator class's functional interface, it may be necessary to pass some information to achieve the corresponding function, such as its name or other useful information in the current environment, etc.)
3. Code implementation of mediator pattern
Written in the front, this code implementation is the most complex design pattern implementation I wrote, and the implementation process is also poorly written. But I still feel that I have not expressed the real meaning of the intermediary model after writing. Even my case does not need the intermediary model to realize, so there are more points to be improved. If some students see this code in the future, you are welcome to point out the optimization scheme.
_With regard to the code implementation of the mediator pattern, I have built a case myself:
- Student Student Class: This is a school where each student has his own name, strong skill, weak shortcoming, and a paired class m_mediator. The type of m_mediator is map < string, Mediator*>. From this, there are also functions of SetMediator for selecting paired classes and UseMediator for paired classes.
- Specific Student Class: There are three kinds of students in the school at present, Normal Student, Sport Student and Art Student, which all inherit from the parent class.
- Matched classes: Matched classes are classes for different types of students (i.e. they can't be paired with the same type of students). Matched classes have three functions: Normal WithSport (string) matched by Normal Student and Sport Student, and Normal Art (string) matched by Normal Student and Art Student. Sport Student and Art Student's matching Art WithSport (string) are three virtual functions, that is, the functions that schools need matching classes to achieve, and the realization of these functions is achieved through specific matching classes.
- Specific Mediator matching classes: There are three matching classes in the school, Skill2Shortcoming_Mediator (commonly known as complementary), Skill2Skill_Mediator (commonly known as strong and strong) and Shortcoming2Shortcoming_Mediator (commonly known as hugging group heating). Three types of students can join these three paired classes at will, so there are three kinds of variables stored in each paired class as follows:
M_normal student, m_sportstudent and m_artstudent are all map structures.
So in pairs, there are also functions AddNormal Student, AddSport Student and Add Art Student that add variables to the map Libraries of the three paired classes.
Therefore, the implementation process of this case is as follows:
- Establish all student files and create digits for different types of students (such as normal_mike);
- Three different paired classes were set up, one for each class (skill2shortcoming_1, for example).
- According to the information of the whole school, all the students are added to the library of three paired classes. (Using AddNormal Student and other functions)
- Distribution of information to students about three classes, students choose which classes they want to attend, and add the class to their schedule; (Use SetMediator function)
- Students (such as normal_mike) decide which class they want to attend, and then choose which matching method (using the UseMediator function) to use in the class.
In summary, the code implementation process of this example is as follows: (In fact, there is a small bug in the logic of cost and benefit, which should be based on what paired classes Student chose, and then paired according to the data selected in the paired classes. This is a direct compulsory way to enroll all the students in the class, so that each student has the right to choose a pair on his own initiative, but he can not avoid being paired by himself. Matching happens)
(I thought about how to solve this problem. It's better to store Student's information in the map structure of the corresponding matching class Mediator when SetMediator, instead of forcing all students'information to be added to it at the beginning.)
#include <iostream> #include <string> #include <map> using namespace std; class Mediator { public: virtual void NormalWithSport(string) = 0; virtual void NormalWithArt(string) = 0; virtual void ArtWithSport(string) = 0; }; class Student { public: Student(string name, string skill,string shortcoming) : m_name(name), m_skill(skill),m_shortcoming(shortcoming) { m_mediator = new map<string, Mediator*>; } void SetMediator(string name, Mediator* mediator) { m_mediator->insert({ name,mediator }); } string getName() { return m_name; } string getSkill() { return m_skill; } string getShortcoming() { return m_shortcoming; } virtual void UseMediator(string, int) = 0; protected: string m_name; string m_skill; string m_shortcoming; map<string, Mediator*>* m_mediator; }; class NormalStudent : public Student { public: NormalStudent(string name, string skill, string shortcoming) : Student(name, skill, shortcoming) {} void UseMediator(string mediatorname,int num) { if (num == 1) m_mediator->at(mediatorname)->NormalWithSport(m_name); if (num == 2) m_mediator->at(mediatorname)->NormalWithArt(m_name); if (num == 3) { m_mediator->at(mediatorname)->NormalWithSport(m_name); m_mediator->at(mediatorname)->NormalWithArt(m_name); } } }; class SportStudent : public Student { public: SportStudent(string name, string skill, string shortcoming) : Student(name, skill, shortcoming) {} void UseMediator(string mediatorname, int num) { if (num == 1) m_mediator->at(mediatorname)->NormalWithSport(m_name); if (num == 2) m_mediator->at(mediatorname)->ArtWithSport(m_name); if (num == 3) { m_mediator->at(mediatorname)->NormalWithSport(m_name); m_mediator->at(mediatorname)->ArtWithSport(m_name); } } }; class ArtStudent : public Student { public: ArtStudent(string name, string skill, string shortcoming) : Student(name, skill, shortcoming) {} void UseMediator(string mediatorname, int num) { if (num == 1) m_mediator->at(mediatorname)->NormalWithArt(m_name); if (num == 2) m_mediator->at(mediatorname)->ArtWithSport(m_name); if (num == 3) { m_mediator->at(mediatorname)->NormalWithArt(m_name); m_mediator->at(mediatorname)->ArtWithSport(m_name); } } }; class Skill2Shortcoming_Mediator : public Mediator { public: Skill2Shortcoming_Mediator() { m_normalstudent = new map<string, NormalStudent*>; m_sportstudent = new map<string, SportStudent*>; m_artstudent = new map<string, ArtStudent*>; } void AddNormalStudent(NormalStudent* normalstudent) { m_normalstudent->insert({ normalstudent->getName(), normalstudent }); } void AddSportStudent(SportStudent* sportstudent) { m_sportstudent->insert({ sportstudent->getName(),sportstudent }); } void AddArtStudent(ArtStudent* artstudent) { m_artstudent->insert({ artstudent->getName(),artstudent }); } void NormalWithSport(string name) { if (m_normalstudent->at(name) != NULL) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_sportstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else if (m_sportstudent->at(name) != NULL) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_normalstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "SportStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "SportStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to NormalStudent or SportStudent" << endl; } } void NormalWithArt(string name) { if (m_normalstudent->at(name) != NULL) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else if ((*m_normalstudent)[name] != NULL) { auto s1 = (*m_normalstudent)[name]; for (auto &s2 : *m_normalstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "ArtStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "ArtStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to NormalStudent or ArtStudent" << endl; } } void ArtWithSport(string name) { if ((*m_normalstudent)[name] != NULL) { auto s1 = (*m_normalstudent)[name]; for (auto &s2 : *m_sportstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "ArtStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "ArtStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else if (m_sportstudent->at(name) != NULL) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getSkill() == s2.second->getShortcoming()) cout << "SportStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Skill " << s2.second->getShortcoming() << endl; if (s1->getShortcoming() == s2.second->getSkill()) cout << "SportStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to SportStudent or ArtStudent" << endl; } } private: map<string, NormalStudent*>* m_normalstudent; map<string, SportStudent*>* m_sportstudent; map<string, ArtStudent*>* m_artstudent; }; class Skill2Skill_Mediator : public Mediator { public: Skill2Skill_Mediator() { m_normalstudent = new map<string, NormalStudent*>; m_sportstudent = new map<string, SportStudent*>; m_artstudent = new map<string, ArtStudent*>; } void AddNormalStudent(NormalStudent* normalstudent) { m_normalstudent->insert({ normalstudent->getName(),normalstudent }); } void AddSportStudent(SportStudent* sportstudent) { m_sportstudent->insert({ sportstudent->getName(),sportstudent }); } void AddArtStudent(ArtStudent* artstudent) { m_artstudent->insert({ artstudent->getName(),artstudent }); } void NormalWithSport(string name) { if (m_normalstudent->find(name) != m_normalstudent->end()) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_sportstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else if (m_sportstudent->find(name) != m_sportstudent->end()) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_normalstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "SportStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to SportStudent or NormalStudent" << endl; } } void NormalWithArt(string name) { if (m_normalstudent->find(name) != m_normalstudent->end()) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "NormalStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else if (m_artstudent->find(name) != m_artstudent->end()) { auto s1 = m_artstudent->at(name); for (auto &s2 : *m_normalstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "ArtStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to ArtStudent or NormalStudent" << endl; } } void ArtWithSport(string name) { if (m_artstudent->find(name) != m_artstudent->end()) { auto s1 = (*m_artstudent)[name]; for (auto &s2 : *m_sportstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "ArtStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else if (m_sportstudent->find(name) != m_sportstudent->end()) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getSkill() == s2.second->getSkill()) cout << "SportStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Skill " << s2.second->getSkill() << endl; } } else { cout << "the student don't belong to ArtStudent or SportStudent" << endl; } } private: map<string, NormalStudent*>* m_normalstudent; map<string, SportStudent*>* m_sportstudent; map<string, ArtStudent*>* m_artstudent; }; class Shortcoming2Shortcoming_Mediator : public Mediator { public: Shortcoming2Shortcoming_Mediator() { m_normalstudent = new map<string, NormalStudent*>; m_sportstudent = new map<string, SportStudent*>; m_artstudent = new map<string, ArtStudent*>; } void AddNormalStudent(NormalStudent* normalstudent) { m_normalstudent->insert({ normalstudent->getName(),normalstudent }); } void AddSportStudent(SportStudent* sportstudent) { m_sportstudent->insert({ sportstudent->getName(),sportstudent }); } void AddArtStudent(ArtStudent* artstudent) { m_artstudent->insert({ artstudent->getName(),artstudent }); } void NormalWithSport(string name) { if (m_normalstudent->find(name) != m_normalstudent->end()) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_sportstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "NormalStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else if (m_sportstudent->find(name) != m_sportstudent->end()) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_normalstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "SportStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else { cout << "the student don't belong to SportStudent or NormalStudent" << endl; } } void NormalWithArt(string name) { if (m_normalstudent->find(name) != m_normalstudent->end()) { auto s1 = m_normalstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "NormalStudent " << s1->getName() << " can be mate with ArtStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else if (m_artstudent->find(name) != m_artstudent->end()) { auto s1 = (*m_artstudent)[name]; for (auto &s2 : *m_normalstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "ArtStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else { cout << "the student don't belong to ArtStudent or NormalStudent" << endl; } } void ArtWithSport(string name) { if (m_artstudent->find(name) != m_artstudent->end()) { auto s1 = (*m_artstudent)[name]; for (auto &s2 : *m_sportstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "ArtStudent " << s1->getName() << " can be mate with SportStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else if (m_sportstudent->find(name) != m_sportstudent->end()) { auto s1 = m_sportstudent->at(name); for (auto &s2 : *m_artstudent) { if (s1->getShortcoming() == s2.second->getShortcoming()) cout << "SportStudent " << s1->getName() << " can be mate with NormalStudent " << s2.second->getName() << " by Shortcoming " << s2.second->getShortcoming() << endl; } } else { cout << "the student don't belong to ArtStudent or SportStudent" << endl; } } private: map<string, NormalStudent*>* m_normalstudent; map<string, SportStudent*>* m_sportstudent; map<string, ArtStudent*>* m_artstudent; }; int main() { //1. The Definition Process of Students NormalStudent* normal_mike = new NormalStudent("mike", "math", "soccer"); NormalStudent* normal_jack = new NormalStudent("jack", "english", "basketball"); NormalStudent* normal_wide = new NormalStudent("wide", "run", "physical"); SportStudent* sport_liuxiang = new SportStudent("liuxiang", "run", "math"); SportStudent* sport_yaoming = new SportStudent("yaoming", "basketball", "english"); SportStudent* sport_zhengzhi = new SportStudent("zhengzhi", "soccer", "paint"); SportStudent* sport_sunyang = new SportStudent("sunyang", "swim", "sing"); ArtStudent* art_linda = new ArtStudent("linda", "paint", "english"); ArtStudent* art_lily = new ArtStudent("lily", "sing", "swim"); ArtStudent* art_sam = new ArtStudent("sam", "dance", "physical"); //2. The Definition Process of Paired Classes Skill2Shortcoming_Mediator* skill2shortcoming_1 = new Skill2Shortcoming_Mediator; Skill2Skill_Mediator* skill2skill_1 = new Skill2Skill_Mediator; Shortcoming2Shortcoming_Mediator* shortcoming2shortcoming_1 = new Shortcoming2Shortcoming_Mediator; //3. Information addition process of paired classes (each paired class obtains all student information according to student files) skill2shortcoming_1->AddNormalStudent(normal_mike); skill2shortcoming_1->AddNormalStudent(normal_jack); skill2shortcoming_1->AddNormalStudent(normal_wide); skill2shortcoming_1->AddSportStudent(sport_liuxiang); skill2shortcoming_1->AddSportStudent(sport_yaoming); skill2shortcoming_1->AddSportStudent(sport_zhengzhi); skill2shortcoming_1->AddSportStudent(sport_sunyang); skill2shortcoming_1->AddArtStudent(art_linda); skill2shortcoming_1->AddArtStudent(art_lily); skill2shortcoming_1->AddArtStudent(art_sam); skill2skill_1->AddNormalStudent(normal_mike); skill2skill_1->AddNormalStudent(normal_jack); skill2skill_1->AddNormalStudent(normal_wide); skill2skill_1->AddSportStudent(sport_liuxiang); skill2skill_1->AddSportStudent(sport_yaoming); skill2skill_1->AddSportStudent(sport_zhengzhi); skill2skill_1->AddSportStudent(sport_sunyang); skill2skill_1->AddArtStudent(art_linda); skill2skill_1->AddArtStudent(art_lily); skill2skill_1->AddArtStudent(art_sam); shortcoming2shortcoming_1->AddNormalStudent(normal_mike); shortcoming2shortcoming_1->AddNormalStudent(normal_jack); shortcoming2shortcoming_1->AddNormalStudent(normal_wide); shortcoming2shortcoming_1->AddSportStudent(sport_liuxiang); shortcoming2shortcoming_1->AddSportStudent(sport_yaoming); shortcoming2shortcoming_1->AddSportStudent(sport_zhengzhi); shortcoming2shortcoming_1->AddSportStudent(sport_sunyang); shortcoming2shortcoming_1->AddArtStudent(art_linda); shortcoming2shortcoming_1->AddArtStudent(art_lily); shortcoming2shortcoming_1->AddArtStudent(art_sam); //4. The process of students choosing to join a paired class by themselves (only a few students are selected here) normal_mike->SetMediator("skill2shortcoming_1", skill2shortcoming_1); normal_mike->SetMediator("skill2skill_1", skill2skill_1); normal_mike->SetMediator("shortcoming2shortcoming_1", shortcoming2shortcoming_1); sport_liuxiang->SetMediator("skill2shortcoming_1", skill2shortcoming_1); sport_liuxiang->SetMediator("skill2skill_1", skill2skill_1); sport_liuxiang->SetMediator("shortcoming2shortcoming_1", shortcoming2shortcoming_1); art_linda->SetMediator("skill2shortcoming_1", skill2shortcoming_1); art_linda->SetMediator("skill2skill_1", skill2skill_1); art_linda->SetMediator("shortcoming2shortcoming_1", shortcoming2shortcoming_1); //5. Students choose the matching mode in the matching classes they join and complete the class (the different functions of the intermediary are different, but the matching is not their own type of students). //The functional numbers 123, 1 and 2 of the intermediary refer to the pairing of two different types of students, and 3 refers to the pairing of all students. cout << normal_mike->getName() << "'s match process!" << endl; normal_mike->UseMediator("skill2shortcoming_1", 1); normal_mike->UseMediator("skill2shortcoming_1", 2); normal_mike->UseMediator("skill2shortcoming_1", 3); cout << sport_liuxiang->getName() << "'s match process!" << endl; sport_liuxiang->UseMediator("skill2skill_1", 1); sport_liuxiang->UseMediator("skill2skill_1", 2); sport_liuxiang->UseMediator("skill2skill_1", 3); cout << art_linda->getName() << "'s match process!" << endl; art_linda->UseMediator("shortcoming2shortcoming_1", 1); art_linda->UseMediator("shortcoming2shortcoming_1", 2); art_linda->UseMediator("shortcoming2shortcoming_1", 3); return 0; }