中介者模式
- 一、概述
- 二、结构
- 三、实例
- 四、优缺点
- 五、适用场景
一、概述
描述:在租房时,租客需要联系中介,中介通过联系房主,构建起联系关系。
定义:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
二、结构
- 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法;定义一个接口用于与各同事对象通信;
- 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,了解并维护它的各个同事,因此它依赖于同事角色;
- 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能;
- 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象通信/交互时,与中介者通信即可,而后由中介者对象负责后续的交互;因此每一个具体同事类需要知道中介者对象,而不需要了解其他同事类的情况。
三、实例
//
//中介者模式
//关键代码:对象 Colleague 之间的通信封装到一个类中单独处理
//
#include<iostream>
#include<string>
#include<memory>
#include<vector>
using namespace std;
class Mediator;
//抽象人
class Person {
protected:
shared_ptr<Mediator> m_mediator; //中介
public:
Person(const shared_ptr<Mediator> pMediator)
: m_mediator(pMediator) {}
virtual ~Person() = default;//虚析构函数
//向中介发送信息
virtual void SendMessage(const string& message) = 0;
//从中介获取信息
//message 中介向该对象发送的信息/从中介获取的信息
virtual void GetMessage(const string& message) = 0;
};
//抽象中介机构
class Mediator {
public:
virtual ~Mediator() = default;
//由于后面this指针的原因,此处未采用智能指针
virtual void Send(string message, const Person* from_person) const = 0;
virtual void Register(shared_ptr<Person> pPerson) = 0;
};
//租房者A
class RenterA : public Person {
public:
RenterA(const shared_ptr<Mediator> mediator) : Person(mediator) {}
void SendMessage(const string& message) override {
m_mediator->Send(message, this);
}
void GetMessage(const string& message) override {
cout << "租房者A收到信息" << message << endl;
}
};
//租房者B
class RenterB : public Person {
public:
RenterB(const shared_ptr<Mediator> mediator) : Person(mediator) {}
void SendMessage(const string& message) override {
m_mediator->Send(message, this);
}
void GetMessage(const string& message) override {
cout << "租房者B收到信息" << message <<endl;
}
};
//房东
class Landlord : public Person {
public:
Landlord(const shared_ptr<Mediator> mediator) : Person(mediator) {}
void SendMessage(const string& message) override {
m_mediator->Send(message, this);
}
void GetMessage(const string& message) override {
cout << "房东收到信息:" << message << endl;
}
};
//房屋中介
class HouseMediator : public Mediator {
private:
//也可以采用多个list,将多个房东放入一个list,将多个求租者放入一个list
vector<shared_ptr<Person>> m_pPersonList;
public:
void Register(const shared_ptr<Person> pPerson) override {
//没有添加该同事,则添加进去
auto iter = m_pPersonList.begin();
for (; iter != m_pPersonList.end(); ++iter) {
if (*iter == pPerson)
break;
}
if (iter == m_pPersonList.end())
m_pPersonList.emplace_back(pPerson);
}
void Send(string message, const Person* from_person) const override {
//接收消息的对象为该对象的对应对象
//
for (const auto item : m_pPersonList) {
//此处采用typeid,而非直接判断指针是否相等为同一个对象.
// 具体何种方式,一般区别不大,视情况而定
if (typeid(*item.get()) != typeid(*from_person))
//if( item.get() != from_person)
item->GetMessage(message);
}
}
};
//客户端
int main() {
// Mediator* pHouseMediator = new HouseMediator();
shared_ptr<Mediator> pHouseMediator = make_shared<HouseMediator>();
/*
多态的要素:子类重写父类的成员函数(override); 父类指针指向子类对象;
利用父类指针调用重写的成员函数。
父类指针指向子类对象;利用父类指针调用重写的成员函数。
*/
shared_ptr<Person> pRenterA = make_shared<RenterA>(pHouseMediator);
shared_ptr<Person> pRenterB = make_shared<RenterB>(pHouseMediator);
shared_ptr<Person> pLandlord =make_shared<Landlord>(pHouseMediator);
pHouseMediator->Register(pRenterA);
pHouseMediator->Register(pRenterB);
pHouseMediator->Register(pLandlord);
pLandlord->SendMessage("出租房");//所有的求租者将会收到该消息
cout << string(50, '-') << std::endl;
pRenterA->SendMessage("租房");//所有的房东将会收到该消息
return 0;
}
四、优缺点
优点:
- 降低了类的复杂度,将一对多关联转化成了一对一的关联,提高了系统的灵活性,使得系统易于维护和扩展;
- .降低了对象之间的耦合性,使得对象易于独立地被复用;
- 符合迪米特原则:只与你最直接的朋友交流。
缺点:
- 当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
五、适用场景
- 对象和其他对象紧密耦合以致难以对其进行修改时,可使用中介者模式。
- 当组件因过于依赖其他组件而无法在不同应用中复用时,可使用中介者模式。
- 为了能在不同情景下复用一些基本行为,导致你需要被迫创建大量组件子类时,可使用中介者模式。