1.定义
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
2.介绍
意图:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
主要解决:对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
何时使用:多个类相互耦合,形成了网状结构。
如何解决:将上述网状结构分离为星型结构。
关键代码:对象 Colleague 之间的通信封装到一个类中单独处理。
应用实例: 1、中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。 2、机场调度系统。 3、MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。
优点: 1、降低了类的复杂度,将一对多转化成了一对一。 2、各个类之间的解耦。 3、符合迪米特原则。
缺点:中介者会庞大,变得复杂难以维护。
使用场景: 1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。 2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
典型例子:电脑主板,电脑的CPU、内存、显卡等配件之间需要相互交互,通过主板即可。
注意事项:不应当在职责混乱的时候使用。
3.示例代码
#include<iostream>
#include<map>
#include<ctime>
#include<sstream>
using namespace std;
class AbstractChatroom;
//抽象同事类
class Member {
protected:
AbstractChatroom* chatroom;
string name;
public:
Member(string name) {
this->name = name;
}
AbstractChatroom* getChatroom() {
return chatroom;
}
void setChatroom(AbstractChatroom* chatroom) {
this->chatroom = chatroom;
}
string getName() {
return name;
}
void setName(string name) {
this->name = name;
}
virtual void sendText(string to, string message) = 0;
virtual void sendImage(string to, string image) = 0;
void receiveText(string from, string message) {
cout << from << "发送文本给" << this->name << ",内容为:" << message << endl;
}
void receiveImage(string from, string image) {
cout << from << "发送图片给" << this->name << ",内容为:" << image << endl;
}
};
string replace(string strSrc, const string& oldStr, const string& newStr, int count = -1)
{
string strRet = strSrc;
size_t pos = 0;
int l_count = 0;
if (-1 == count) //替换所有
count = strRet.size();
while ((pos = strRet.find(oldStr, pos)) != string::npos)
{
strRet.replace(pos, oldStr.size(), newStr);
if (++l_count >= count) break;
pos += newStr.size();
}
return strRet;
}
//抽象中介者类
class AbstractChatroom {
public:
virtual void registers(Member* member) = 0;
virtual void sendText(string from, string to, string message) = 0;
virtual void sendImage(string from, string to, string image) = 0;
};
//具体中介者类
class ChatGroup : public AbstractChatroom {
private:
map<string, Member*> members;
map<string, Member*>::iterator iter;
public:
void registers(Member* member) {
iter = members.find(member->getName());
if (iter == members.end()) {
members.insert(map<string, Member*>::value_type(member->getName(), member));
member->setChatroom(this);
}
}
void sendText(string from, string to, string message) {
Member* member = members.find(to)->second;
string newMessage = message;
newMessage = replace(message, "日", "*");
member->receiveText(from, newMessage);
}
void sendImage(string from, string to, string image) {
Member* member = members.find(to)->second;
if (image.length() > 5) {
cout << "图片太大,发送失败" << endl;
}
else {
member->receiveImage(from, image);
}
}
};
//具体中介者类
class NewChat :public AbstractChatroom {
private:
map<string, Member*> members;
map<string, Member*>::iterator iter;
public:
void registers(Member* member) {
iter = members.find(member->getName());
if (iter == members.end()) {
members.insert(map<string, Member*>::value_type(member->getName(), member));
member->setChatroom(this);
}
}
void sendText(string from, string to, string message) {
Member* member = members.find(to)->second;
string newMessage = message;
newMessage = replace(message, "日", "*");
if (message.length() > 100) {
cout << "发送的文字长度不得超过100个字符,发送失败" << endl;
}
else {
member->receiveText(from, newMessage);
}
}
void sendImage(string from, string to, string image) {
Member* member = members.find(to)->second;
if (image.length() > 20) {
cout << "图片大小不得超过20M,发送失败" << endl;
}
else {
member->receiveImage(from, image);
}
}
};
//具体同事类
class CommonMember :public Member {
protected:
string name;
public:
CommonMember(string name) :Member(name) {
this->name = name;
}
void sendText(string to, string message) {
cout << "普通会员发送消息:" << endl;
chatroom->sendText(this->name, to, message);
}
void sendImage(string to, string image) {
cout << "普通会员不能发送图片!" << endl;
}
};
//具体同事类
class DiamondMember :public Member {
protected:
string name;
public:
DiamondMember(string name) :Member(name) {
this->name = name;
}
void sendText(string to, string message) {
cout << "钻石会员发送消息:" << endl;
chatroom->sendText(name, to, message);
}
void sendImage(string to, string image) {
cout << "钻石会员发送图片:" << endl;
chatroom->sendImage(name, to, image);
}
};
//具体同事类
class NewMember :public Member {
protected:
string name;
public:
NewMember(string name) :Member(name) {
this->name = name;
}
void sendText(string to, string message) {
time_t now = time(NULL);
tm* t = localtime(&now);
// 将信息输出到字符串流
stringstream ss;
stringstream ss2;
ss << t->tm_year + 1900 << "." << t->tm_mon + 1 << "." <<
t->tm_mday << ".." << t->tm_hour << "." << t->tm_min << "." << t->tm_sec;
cout << "新会员发送消息:" << endl;
chatroom->sendText(name, to, message + " 现在时间" + ss.str());
}
void sendImage(string to, string image) {
cout << "会员发送图片:" << endl;
chatroom->sendImage(name, to, image);
}
};
//测试函数
int main() {
AbstractChatroom* newChat = new NewChat();
Member* member1, * member2, * member3, * member4;
member1 = new DiamondMember("张三");
member2 = new CommonMember("小李");
member3 = new NewMember("小芳");
member4 = new NewMember("小红");
newChat->registers(member1);
newChat->registers(member2);
newChat->registers(member3);
newChat->registers(member4);
member1->sendText("小李", "小李,你好!");
member2->sendText("张三", "张三,你好!");
cout << "---------------------------------------------" << endl;
member3->sendText("小红", "小红你好。");
member3->sendText("小红", "你好小红!-----------------------------------------------------------------------------------------------------");
member3->sendImage("小红", "哈哈.jpg");
member4->sendText("小芳", "你好,小芳");
member4->sendImage("小芳", "哈哈.jpg--------------------");
}
4.引用
1.中介者模式详解(作用优缺及应用场景实例) – mikechen
3.中介者模式——C++实现 - 戈瑾 - 博客园 (cnblogs.com)