设计模式---中介者模式

定义与设计思路

  • 定义:用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,属于行为型模式。

  • 设计思路:用一个中介对象来封装一系列的对象交互操作,中介者模式使得对象之间不需要显示的相互引用,从而使得系统或模块内部相互解耦,而且可以独立的改变它们至今的交互

中介者模式的引入:机场控制塔

想象一个繁忙的机场,有许多飞机在同一时间内起飞和降落。如果每架飞机都直接与其他飞机通信,协商谁该先起飞、谁该先降落,整个机场的调度将变得非常复杂。每架飞机都要知道其他所有飞机的状态、飞行路线、优先级等,导致信息的传递和处理变得混乱而低效。

问题:飞机之间的复杂通信
直接通信导致混乱: 每架飞机要知道并与其他所有飞机通信,管理起飞、降落的顺序会变得非常困难且危险。

  • 维护成本高: 增加或移除一架飞机,所有飞机的通信方式都需要更新,增加了维护的难度。
  • 耦合度过高: 每架飞机相互依赖,任何一个飞机的变动可能会影响整个系统的稳定性。

中介模式解决问题:引入机场控制塔
为了简化调度过程,机场引入了控制塔作为中介者。控制塔的职责是协调所有飞机的起飞和降落,保证每架飞机都能安全有- 序地运行。这样,每架飞机只需要与控制塔通信,而不需要关心其他飞机的具体状态。

  • 控制塔(中介者): 控制飞机的起飞和降落顺序,管理它们的路线和时间安排。
  • 飞机(同事类): 负责向控制塔报告自己的状态(如准备起飞、准备降落等),并接收控制塔的指令(如可以起飞或等待)。

中介模式的作用:
去耦合: 飞机之间不再直接通信,只需要和控制塔交互,这大大简化了飞机之间的相互依赖。
集中控制: 所有的调度逻辑都集中在控制塔中,便于统一管理,维护起来更加简单。
易于扩展: 新的飞机可以轻松加入机场系统,只需要和控制塔通信,而不需要重新调整其他飞机的通信逻辑。

中介者模式的设计框架

需要一个中介者类和同事类,目的是通过中介者类对象对象完成同事类实例之间的信息交互。其中,中介者类中需要有一个储存注册进来的同事对象的列表、发送消息的接口(协助同事实例完成消息的转发)、注册函数(完成同事实例的注册)。所有的同事类实例包含一个发布消息接口、接收消息的接口(接收中介转发的消息),另外包含一个中介实例成员变量(用于完成消息的转发的接口对象)。

中介模式的关键要素:

  • 中介者(Mediator): 中介者负责定义对象之间的通信接口,具体的通信逻辑则由具体的中介者实现。
  • 具体中介者(Concrete Mediator): 这是中介者的具体实现,它维护所有参与者对象,并处理这些对象之间的通信。
  • 同事类(Colleague): 这些是参与通信的对象,它们通过中介者进行相互通信,而不是直接引用其他同事对象。
#include <bits/stdc++.h>


//
//中介者模式
//关键代码:对象 Colleague 之间的通信封装到一个类中单独处理
//

class Mediator;

//抽象人(同事类)
class Person
{
protected:
    std::shared_ptr<Mediator> m_mediator; //中介类实例
public:
    Person(const std::shared_ptr<Mediator> pMediator) : m_mediator(pMediator) {}

	//虚析构函数
    virtual ~Person() = default;

    //向中介发送信息
    virtual void SendMessage(const std::string &message) = 0;

    //从中介获取信息
    //message 中介向该对象发送的信息/从中介获取的信息
    virtual void GetMessage(const std::string &message) = 0;
};

//抽象中介机构
class Mediator
{
public:
    virtual ~Mediator() = default;

    //由于后面this指针的原因,此处未采用智能指针
    virtual void Send(std::string message, const Person *from_person) const = 0;

    virtual void Register(std::shared_ptr<Person> pPerson) = 0;
};

//租房者A
class RenterA : public Person
{
public:
    RenterA(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}

    void SendMessage(const std::string &message) override
    {
      m_mediator->Send(message, this);
    }

    void GetMessage(const std::string &message) override
    {
      std::cout << "租房者A收到信息" << message << std::endl;;
    }
};

//租房者B
class RenterB : public Person
{
public:
    RenterB(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}

    void SendMessage(const std::string &message) override
    {
      m_mediator->Send(message, this);
    }

    void GetMessage(const std::string &message) override
    {
      std::cout << "租房者B收到信息" << message << std::endl;;
    }
};


//房东
class Landlord : public Person
{
public:
    Landlord(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}

    void SendMessage(const std::string &message) override
    {
      m_mediator->Send(message, this);
    }

    void GetMessage(const std::string &message) override
    {
      std::cout << "房东收到信息:" << message << std::endl;;
    }
};

//房屋中介
class HouseMediator : public Mediator
{
private:
    //也可以采用多个list,将多个房东放入一个list,将多个求租者放入一个list
    std::vector<std::shared_ptr<Person>> m_pPersonList;
public:
    void Register(const std::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(std::string message, const Person *from_person) const override
    {
      //接收消息的对象为该对象的对应对象
      for (const auto item:m_pPersonList)
      {
        //此处采用typeid,而非直接判断指针是否相等为同一个对象.
        if (typeid(*item.get()) != typeid(*from_person))
        {
          item->GetMessage(message);
        }
      }
    }
};

int main() {
  std::shared_ptr<Mediator> pHouseMediator = std::make_shared<HouseMediator>();
  std::shared_ptr<Person> pRenterA = std::make_shared<RenterA>(pHouseMediator);
  std::shared_ptr<Person> pRenterB = std::make_shared<RenterB>(pHouseMediator);
  std::shared_ptr<Person> pLandlord = std::make_shared<Landlord>(pHouseMediator);

  pHouseMediator->Register(pRenterA);
  pHouseMediator->Register(pRenterB);
  pHouseMediator->Register(pLandlord);

  pLandlord->SendMessage("出租房子:中山路100号,50平米,2000元一个月");//所有的求租者将会收到该消息

  std::cout << std::string(50, '-') << std::endl;

  pRenterA->SendMessage("我想在中山路附近租套房子,价格1500元一个月");//所有的房东将会收到该消息

  return 0;
}

输出

租房者A收到信息出租房子:中山路100号,50平米,2000元一个月
租房者B收到信息出租房子:中山路100号,50平米,2000元一个月
--------------------------------------------------
租房者B收到信息我想在中山路附近租套房子,价格1500元一个月
房东收到信息:我想在中山路附近租套房子,价格1500元一个月

发送的消息通过中介转发给租房者,租房者发送的消息通过中介转发给

感谢大佬的讲解

https://blog.csdn.net/leonardohaig/article/details/109963550

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光技术人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值