篇一:
简介】
-- 什么是中介者模式 (第16种模式)
中介者模式(Mediator Pattern)也被称为调停者模式,是⼀种⾏为型设计模式,它通过⼀个中介对象来封装⼀组对象之间的交互,从⽽使这些对象不需要直接相互引⽤。这样可以降低对象之间的耦合度,使系统更容易维护和扩展。
当⼀个系统中的对象有很多且多个对象之间有复杂的相互依赖关系时,其结构图可能是下⾯这样的。
这种依赖关系很难理清,这时我们可以引⼊⼀个中介者对象来进⾏协调和交互。中介者模式可以使得系统的⽹状结构变成以中介者为中⼼的星形结构,每个具体对象不再通过直接的联系与另⼀个对象发⽣相互作⽤,⽽是通过“中介者”对象与另⼀个对象发⽣相互作⽤。
【基本结构】
中介者模式包含以下⼏个基本角色:
抽象中介者(Mediator): 定义中介者的接⼝,⽤于各个具体同事对象之间的通信。
具体中介者(Concrete Mediator): 实现抽象中介者接⼝,负责协调各个具体同事对象的交互关系,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令。
抽象同事类(Colleague): 定义同事类的接⼝,维护⼀个对中介者对象的引⽤,⽤于通信。
具体同事类(Concrete Colleague): 实现抽象同事类接⼝,每个具体同事类只知道⾃⼰的⾏为,⽽不了解其他同事类的情况,因为它们都需要与中介者通信,通过中介者协调与其他同事对象的交互。
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
// 类的定义
// 抽象中介者类
class ChatRoomMediator
{
// 成员接口函数
public:
// 获取所有的用户类
virtual std::map<string, ChatUser*> GetUsers() = 0;
// 添加用户至中介类
virtual void AddUser(ChatUser *user) = 0;
// 中介者发送信息 至其他的所有用户
virtual void SendMessage(string sender, string message) = 0;
};
// 具体中介者类
class ChatRoomMediatorImpl : public ChatRoomMediator
{
// 成员数据
private:
std::map <string, ChatUser*> _chatUsers;//集合<用户名称, 具体用户>
// 成员函数接口
public:
// 获取所有的用户类 重载
std::map<string, ChatUser*> GetUsers() override
{
return _chatUsers;
}
// 添加用户至中介类 重载
void AddUser(ChatUser *user) override
{
_chatUsers.insert(std::pair<string, ChatUser*>(user->GetName(), user));
}
// 中介者发送信息 至其他的所有用户 函数重载
void SendMessage(string sender, string message) override
{
for(map<string, ChatUser*>::iterator it = _chatUsers.begin(); it != _chatUsers.end(); it++)
{
if(it->first != sender)//至其他的所有用户(除了发送者之外)
{
it->second->ReceiveMessage(sender, message);
}
}
}
};
// 抽象用户类 -- 接口
class ChatUser
{
// 成员函数接口
public:
// 获取当前的用户姓名
virtual string GetName() = 0;
// 发送信息至其他人(通过中介者来代理)
virtual void SendMessage(string message) = 0;
// 接收信息函数接口
virtual void ReceiveMessage(string sender, string message) = 0;
// 获取所有的信息集
virtual std::vector<string> GetAllMessages() = 0;
protected:
// 将接收到的信息存放至信息集中
virtual void AddRecvMessageIntoVec(string message) = 0;
};
// 具体用户类
class ConcreteChatUser : public ChatUser
{
// 成员数据
private:
string _userName;//用户姓名
ChatRoomMediator * _mediator;//中介者
std::vector<string> _recvMessages;//所有接收到的信息
// 成员函数接口
public:
ConcreteChatUser(string name, ChatRoomMediator *mediator) //构造函数
{
this->_userName = name;
this->_mediator = mediator;
this->_mediator->AddUser(this);
}
// 获取当前的用户姓名
string GetName() override
{
return _userName;
}
// 发送信息至其他人(通过中介者来代理)
void SendMessage(string message) override
{
// 通过中介者去发送信息
_mediator->SendMessage(_userName, message);//(发送者自己姓名,消息)
}
// 接收信息函数接口
void ReceiveMessage(string sender, string message) override
{
string messages = _userName + " received: " + message;
std::cout << messages << endl;
}
// 获取所有的信息集
std::vector<string> GetAllMessages() override
{
return _recvMessages;
}
protected:
// 将接收到的信息存放至信息集中
void AddRecvMessageIntoVec(string message) override
{
_recvMessages.push_back(message);
}
};
int main()
{
// 用户数量
int userNum = 0;
std::cin >> userNum;
// 保存所有的用户
std::vector<string> usersV;
usersV.resize(userNum);
for(int i = 0; i < userNum; i++)
{
std::cin >> usersV[i];
}
// 抽象中介者
ChatRoomMediator *mediator = new ChatRoomMediatorImpl();//new具体中介
// 抽象用户类
ChatUser *user = nullptr;
// 在中介者类中添加所有的用户类
for(int i = 0; i < userNum; i++)
{
// 构造具体的用户类
user = new ConcreteChatUser(usersV[i], mediator);
}
// 此时已经在中介者类中添加了所有的用户
// 遍历 去发送信息
for(int i = 0; i < userNum; i++)
{
// 获取发送者 和 消息
string senderName = "";
string sendMessageInfo = "";
// 输入
std:: cin >> senderName >> sendMessageInfo;
// 用户(发送者senderName)通过中介者mediator:去发送SendMessage消息sendMessageInfo
mediator->SendMessage(senderName, sendMessageInfo);
}
// 析构
if(user != nullptr)
{
delete user;
user = nullptr;
}
delete mediator;
mediator = nullptr;
return 0;
}
【扩展:和代理模式的区别】
中介者模式(Mediator Pattern)和代理模式(Proxy Pattern) 在某些表述上有些类似,但是他们是完全不同的两个设计模式,中介者模式的⽬的是降低系统中各个对象之间的直接耦合,通过引⼊⼀个中介者对象,使对象之间的通信集中在中介者上。而在代理模式中,客户端通过代理与⽬标对象进⾏通信。代理可以在调⽤⽬标对象的⽅法前后进⾏⼀些额外的操作,其⽬的是控制对对象的访问,它们分别解决了不同类型的问题。
原文链接:https://blog.csdn.net/K1_uestc/article/details/135680591
篇二:
1 含义
用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
2 模式结构
中介者承担两方面的职责:
中转作用(结构性):通过中介者提供的中转作用,各个同事对象就不再需要显式引用其他同事,当需要和其他同事进行通信时,通过中介者即可。该中转作用属于中介者在结构上的支持。
协调作用(行为性):中介者可以更进一步的对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对同事的请求进行进一步处理,将同事成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持。
Mediator: 抽象中介者用于定义一个接口,该接口用于与各同事对象之间的通信
ConcreteMediator: 具体中介者是抽象中介者的子类,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事对象的引用
Colleague: 抽象同事类定义各同事的公有方法
ConcreteColleague: 具体同事类的每一个同事对象都引用一个中介者对象;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信
3 代码实现
举例:虚拟聊天室
某论坛系统欲增加一个虚拟聊天室,允许论坛会员通过该聊天室进行信息交流,普通会员(CommonMember)可以给其他会员发送文本信息,钻石会员(DiamondMember)既可以给其他会员发送文本信息,还可以发送图片信息。该聊天室可以对不雅字符进行过滤,如“日”等字符;还可以对发送的图片大小进行控制。用中介者模式设计该虚拟聊天室。
#include<iostream>
#include <string>
#include <map>
using namespace std;
class Member;
//抽象中介者类AbstractChatroom(抽象聊天室类)
class AbstractChatroom {
public:
virtual void registerMember(Member* member) = 0;
virtual void sendText(string from, string to, string message) = 0;
virtual void sendImage(string from, string to, string image) = 0;
};
//抽象同事类Member(抽象会员类)
class Member
{
protected:
AbstractChatroom *chatroom;
string name;
public:
Member(string name) {
this->name = name;
}
string getName() {
return this->name;
}
void setName(string name) {
this->name = name;
}
AbstractChatroom* getChatroom() {
return chatroom;
}
void setChatroom(AbstractChatroom* chatroom) {
this->chatroom = chatroom;
}
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;
}
};
//具体中介者类Chatgroup(具体聊天室类)
class ChatGroup : public AbstractChatroom {
public:
void registerMember(Member* member) {
if (!members.count(member->getName())) {
members.insert(make_pair(member->getName(), member));
member->setChatroom(this);
}
}
void sendText(string from, string to, string message) {
Member *member = members[to];
member->receiveText(from, message);
}
void sendImage(string from, string to, string image) {
Member *member = members[to];
if (image.length() > 5) {
cout << "图片太大,发送失败!" << endl;
}
else {
member->receiveImage(from, image);
}
}
private:
map<string, Member*> members;
};
//具体同事类CommonMember(普通会员类)
class CommonMember : public Member {
public:
CommonMember(string name) : Member(name) {
}
void sendText(string to, string message) {
cout << "普通会员发送信息:" << endl;
chatroom->sendText(name, to, message);
}
void sendImage(string to, string image) {
cout << "普通会员不能发送图片!" << endl;
}
};
//具体同事类DiamondMember(钻石会员类)
class DiamondMember : public Member {
public:
DiamondMember(string name) : Member(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);
}
};
int main(int argc, char* argv[])
{
//创建聊天室
ChatGroup happyChat;
//创建成员
CommonMember member1("张三");
DiamondMember member2("李四");
//注册
happyChat.registerMember(&member1);
happyChat.registerMember(&member2);
//发送信息
member1.sendText("李四", "李四,你好!");
member2.sendText("张三", "张三,你好!");
member1.sendText("李四", "今天天气很不错");
member1.sendImage("李四", "好天气");
member2.sendImage("张三", "一个很大的太阳");
member2.sendImage("张三", "太阳");
}
4 优缺点
4.1 优点
通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,中介者承担了中转作用和协调作用。
简化了对象之间的交互,将各同事解耦,还可以减少子类生成,对于复杂的对象之间的交互,通过引入中介者,可以简化各同事类的设计和实现
4.2 缺点
具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
5 适用场景
系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解;一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象;想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
原文链接:https://blog.csdn.net/cutemypig/article/details/110039394