中介模式是一种行为型设计模式,目的是把多个对象之间的通信集中在一个中介对象中,从而减少对象之间的耦合。中介对象充当了对象间的协调者将对象之间的交互转换为与中介对象的交互,从而降低了对象之间的复杂性。
中介模式适用于多个对象之间相互引用的情况。
中介模式通常有四个“角色”:
1、抽象中介者:定义中介者的接口,它通常包含了对象之间通信的方法。
2、具体中介者:实现抽象中介者定义的接口。
3、抽象同事类:定义具体同事类的行为接口,每个同事负责自己的行为,并与其他同事进行通信。当它需要通知其他对象它的行为发生改变时,应该通知中介者、由中介者通知其他同事。
4、具体同事类:实现抽象同事类的方法,它们通过中介者来与其他同事类进行通信。
举例:
假设我们现在有一个聊天室,一个用户发送一条消息,我们希望所有的对象都可以收到这条消息。
#pragma once
#include
#include
#include
#include
// 抽象同事类
class IUser
{
public:
virtual ~IUser() {}
virtual void SendMessage(const std::string& _msg) = 0;
virtual void RecvMessage(const std::string& _msg) = 0;
};
// 抽象中介者
class IMediator
{
public:
virtual ~IMediator() {}
// 发送消息
virtual void SendMessage(const std::string& _msg, std::shared_ptr<IUser> _sender) = 0;
// 添加同事
virtual void AddUser(std::shared_ptr<IUser> _user) = 0;
};
// 具体中介者
class Mediator
: public IMediator
{
public:
virtual void SendMessage(const std::string& _msg, std::shared_ptr<IUser> _sender) override
{
for (auto user : users_)
{
if(user == _sender)
continue;
user->RecvMessage(_msg);
}
}
// 添加同事
virtual void AddUser(std::shared_ptr<IUser> _user) override
{
if (users_.find(_user) != users_.end())
return;
users_.insert(_user);
}
private:
std::set<std::shared_ptr<IUser>> users_;
};
class User
: public IUser
, public std::enable_shared_from_this<User>
{
public:
User(const std::string& _name, std::shared_ptr<IMediator> _mediator)
{
name_ = _name;
mediator_ = _mediator;
}
virtual void SendMessage(const std::string& _msg) override
{
if (mediator_)
mediator_->SendMessage(_msg, std::dynamic_pointer_cast<IUser>(shared_from_this()));
}
virtual void RecvMessage(const std::string& _msg) override
{
std::cout << name_ << "收到消息:" << _msg << std::endl;
}
private:
std::string name_;
std::shared_ptr<IMediator> mediator_;
};
测试:
void TestMediator()
{
// 中介者
std::shared_ptr<IMediator> mediator = std::make_shared<Mediator>();
// 用户
std::shared_ptr<IUser> user1 = std::make_shared<User>("user1", mediator);
std::shared_ptr<IUser> user2 = std::make_shared<User>("user2", mediator);
std::shared_ptr<IUser> user3 = std::make_shared<User>("user3", mediator);
mediator->AddUser(user1);
mediator->AddUser(user2);
mediator->AddUser(user3);
// 用户发送消息
user1->SendMessage("用户1");
user2->SendMessage("用户2");
user3->SendMessage("用户3");
}
输出:
user2收到消息:用户1
----------------------------
user3收到消息:用户1
----------------------------
user3收到消息:用户2
----------------------------
user1收到消息:用户2
----------------------------
user2收到消息:用户3
----------------------------
user1收到消息:用户3
----------------------------
在示例中,我们定义了抽象中介者类、具体中介者类、抽象同事类、具体同事类。其中具体中介者实现了添加同事和转发消息的方法,具体同事类实现了发送消息和接收消息方法。
测试代码中我们创建一个中介者对象,三个用户对象,并在构造函数中传入用户名和中介者对象。当一个用户名发送消息时,会通过中介者模式进行转发,在输出中我们可以看到用户发送一条消息,其他的用户都接收到了。
通过这种方法,我们就解耦了多个对象之间复杂的交互关系,并将交互转移到中介者身上,避免多个对象直接相互依赖产生的复杂性。
中介者遵循的设计原则:
1、开放封闭原则:当我们想要再添加一个“同事”与其他“同事”进行交互时,只需要添加一个新的同事类,并把它添加到中介者对象中,无需修改现有代码。
2、单一职责原则:中介者对象只负责各个同事之间的交互,同事只负责自己的个人行为,符合单一职责原则。
3、依赖倒置原则:高层模块和底层模块不应该相互依赖,它们都应该依赖抽象。在上述例子中,我们的中介者类和同事类都是依赖对应的抽象类,降低了模块之间的耦合性。
优点:
1、减少了对象之间的直接依赖:将对象之间的通信集中到中介者对象中,降低了系统的耦合度。
2、增强了系统的可扩展性和灵活性:通过中介者对象,我们可以很灵活的引入一个新的同事类,只需要把它添加到中介者对象维护的一个同事类列表中即可,无需修改现有代码。
3、提高了系统的可维护性:中介者模式将复杂对象之间的交互封装在中介者对象,简化了系统的逻辑,易于维护。
缺点:
1、增加了系统的复杂性:随着系统中同事类对象的增加,中介者对象的责任会变得越来越大,可能会变得更复杂,不易维护。
2、中介者对象可能会变得过于“智能”:作为一个统一管理所有对象的管理器,中介者对象需要对所有对象非常了解,从而做出正确的决策,这可能会导致中介者对象变得过于“智能”,代码实现复杂,难以理解和维护。