Chapter14—中介者模式

中介者模式

1 概念

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

2 意图(Intent)

用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

3 动机(Motivate)

在软件构建过程中,经常会出现多个对象互相关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。在这种情况下,我们可使用一个"中介对象"来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。

4 类图结构

5 角色定义

  • Mediator(抽象中介者):抽象中介者用于定义一个接口,该接口用于与各同事对象之间的通信。
  • ConcreteMediator(具体中介者):具体中介者是抽象中介者的子类,通过协调各个同事对象来实现协作行为,了解并维护它对各个同事对象的引用。在通用的中介者模式类图中,具体中介者与各个具体同事类之间有关联关系,在实现时为了保证系统的扩展性,可以根据需要将该引用关联关系建立在抽象层,即具体中介者中定义的是抽象同事角色。
  • Colleague(抽象同事类):抽象同事类定义各同事的公用方法。
  • ConcreteColleague(具体同事类):具体同事类是抽象同事类的子类,每一个同事对象都引用一个中介者对象;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。

6 程序示例

中介者示例

抽象中介者

cpp 复制代码
class Mediator
{
public:
    Mediator() = default;
    virtual ~Mediator() = default;

public:
    virtual void DoActionFromAtoB() = 0;
    virtual void DoActionFromBtoA() = 0;
};

抽象同事类

cpp 复制代码
class Colleage
{
public:
    Colleage() = default;
    virtual ~Colleage() = default;
    Colleage(Mediator* pMediator);

public:
    virtual void Aciton() = 0;
    void SetState(const string& strState);
    string GetState();

protected:
    Mediator* m_pMediator;
    string m_strState;
};

Colleage::Colleage(Mediator *pMediator) : m_pMediator(pMediator)
{
    // ...
}

void Colleage::SetState(const string &strState)
{
    m_strState = strState;
}

string Colleage::GetState()
{
    return m_strState;
}

具体同事类A

cpp 复制代码
class ConcreteColleageA: public Colleage
{
public:
    ConcreteColleageA() = default;
    virtual ~ConcreteColleageA() = default;
    ConcreteColleageA(Mediator* pMediator);

public:
    void Aciton();
};

ConcreteColleageA::ConcreteColleageA(Mediator *pMediator) : Colleage(pMediator)
{
    // ...
}

void ConcreteColleageA::Aciton()
{
    m_pMediator->DoActionFromAtoB();
    qDebug() << "State of ConcreteColleageA:" << this->GetState().c_str();
}

具体同事类B

cpp 复制代码
class ConcreteColleageB: public Colleage
{
public:
    ConcreteColleageB() = default;
    virtual ~ConcreteColleageB() = default;
    ConcreteColleageB(Mediator* pMediator);

public:
    void Aciton();
};

ConcreteColleageB::ConcreteColleageB(Mediator *pMediator) : Colleage(pMediator)
{
    // ...
}

void ConcreteColleageB::Aciton()
{
    m_pMediator->DoActionFromBtoA();
    qDebug() << "State of ConcreteColleageB:" << this->GetState().c_str();
}

具体中介者类

cpp 复制代码
class ConcreteMediator: public Mediator
{
public:
    ConcreteMediator() = default;
    ~ConcreteMediator() = default;
    ConcreteMediator(Colleage* pColleageA, Colleage* pColleageB);

public:
    void SetConcreteColleageA(Colleage* pColleageA);
    void SetConcreteColleageB(Colleage* pColleageB);

    Colleage* GetConcreteColleageA();
    Colleage* GetConcreteColleageB();

    void IntroColleage(Colleage* pColleageA, Colleage* pColleageB);
    void DoActionFromAtoB();
    void DoActionFromBtoA();

private:
    Colleage* m_pColleageA;
    Colleage* m_pColleageB;
};

ConcreteMediator::ConcreteMediator(Colleage *pColleageA, Colleage *pColleageB):
    m_pColleageA(), m_pColleageB(pColleageB)
{
    // ...
}

void ConcreteMediator::SetConcreteColleageA(Colleage *pColleageA)
{
    m_pColleageA = pColleageA;
}

void ConcreteMediator::SetConcreteColleageB(Colleage *pColleageB)
{
    m_pColleageB = pColleageB;
}

Colleage *ConcreteMediator::GetConcreteColleageA()
{
    return m_pColleageA;
}

Colleage *ConcreteMediator::GetConcreteColleageB()
{
    return m_pColleageB;
}

void ConcreteMediator::IntroColleage(Colleage *pColleageA, Colleage *pColleageB)
{
    m_pColleageA = pColleageA;
    m_pColleageB = pColleageB;
}

void ConcreteMediator::DoActionFromAtoB()
{
    m_pColleageB->SetState(m_pColleageA->GetState());
}

void ConcreteMediator::DoActionFromBtoA()
{
    m_pColleageA->SetState(m_pColleageB->GetState());
}

测试函数类

cpp 复制代码
void ClientTest()
{
    ConcreteMediator* pConcreteMediator = new ConcreteMediator();

    ConcreteColleageA* pColleageA = new ConcreteColleageA(pConcreteMediator);
    ConcreteColleageB* pColleageB = new ConcreteColleageB(pConcreteMediator);

    pConcreteMediator->IntroColleage(pColleageA, pColleageB);

    pColleageA->SetState("old");
    pColleageB->SetState("old");

    pColleageA->Aciton();
    pColleageB->Aciton();


    pColleageA->SetState("new");
    pColleageA->Aciton();
    pColleageB->Aciton();


    pColleageB->SetState("old");
    pColleageB->Aciton();
    pColleageA->Aciton();

    delete pConcreteMediator;
    delete pColleageA;
    delete pColleageB;
}

虚拟聊天室示例

示例类图

抽象中介者类 AbstractChatroom (抽象聊天室类)

cpp 复制代码
class Member;

/**
 * @brief 抽象中介者类 AbstractChatroom (抽象聊天室类)
 */
class AbstractChatroom
{
public:
    AbstractChatroom() = default;
    virtual ~AbstractChatroom() = default;

public:
    virtual void Rergister(Member* pMember) = 0;
    virtual void SendText(const string& strFrom, const string& strTo, const string& strMessage) = 0;
    virtual void SendImage(const string& strFrom, const string& strTo, const string& strImage) = 0;
};

抽象同事类 Member (抽象会员类)

cpp 复制代码
/**
 * @brief 抽象同事类 Member (抽象会员类)
 */
class Member
{
public:
    Member(const string& strName);
    virtual ~Member() = default;

public:
    void SetName(const string& strName);
    string GetName();
    void SetChatroom(AbstractChatroom* pChatroom);
    AbstractChatroom* GetChatroom();
    void ReceiveText(const string& strFrom, const string& strMessage);
    void ReceiveImage(const string& strFrom, const string& strImage);

    virtual void SendText(const string& strTo, const string& strMessage) = 0;
    virtual void SendImage(const string& strTo, const string& strImage) = 0;

protected:
    AbstractChatroom* m_pChatroom;
    string m_strName;
};

Member::Member(const string &strName): m_strName(strName)
{
    // ...
}

void Member::SetName(const string &strName)
{
    m_strName = strName;
}

string Member::GetName()
{
    return m_strName;
}

void Member::SetChatroom(AbstractChatroom *pChatroom)
{
    m_pChatroom = pChatroom;
}

AbstractChatroom *Member::GetChatroom()
{
    return m_pChatroom;
}

void Member::ReceiveText(const string &strFrom, const string &strMessage)
{
    qDebug() << strFrom.c_str() << "发送文本给" << m_strName.c_str() << ",内容为:" << strMessage.c_str();
}

void Member::ReceiveImage(const string &strFrom, const string &strImage)
{
    qDebug() << strFrom.c_str() << "发送图片给" << m_strName.c_str() << ",内容为:" << strImage.c_str();
}

具体中介者类 ChatGroup (具体聊天室类)

cpp 复制代码
/**
 * @brief 具体中介者类 ChatGroup (具体聊天室类)
 */
class ChatGroup: public AbstractChatroom
{
public:
    ChatGroup() = default;
    ~ChatGroup() = default;

public:
    void Rergister(Member* pMember) override;
    void SendText(const string& strFrom, const string& strTo, const string& strMessage) override;
    void SendImage(const string& strFrom, const string& strTo, const string& strImage) override;

private:
    map<string, Member*> m_MapName2Member;
};

void ChatGroup::Rergister(Member *pMember)
{
    m_MapName2Member[pMember->GetName()] = pMember;
    pMember->SetChatroom(this);
}

void ChatGroup::SendText(const string &strFrom, const string &strTo, const string &strMessage)
{
    Member* pMember = m_MapName2Member[strTo];
    pMember->ReceiveText(strFrom, strMessage);
}

void ChatGroup::SendImage(const string &strFrom, const string &strTo, const string &strImage)
{
    Member* pMember = m_MapName2Member[strTo];
    if (strImage.length() > 10)
    {
        qDebug() << "图片太大,发送失败!";
    }
    else
    {
        pMember->ReceiveImage(strFrom, strImage);
    }
}

具体同事类 CommonMember(普通会员类)

cpp 复制代码
/**
 * @brief 具体同事类 CommonMember(普通会员类)
 */
class CommonMember: public Member
{
public:
    CommonMember(const string& strName);
    ~CommonMember() = default;

public:
    void SendText(const string& strTo, const string& strMessage) override;
    void SendImage(const string& strTo, const string& strImage) override;
};

CommonMember::CommonMember(const string &strName): Member(strName)
{
    // ...
}

void CommonMember::SendText(const string &strTo, const string &strMessage)
{
    qDebug() << "普通会员发送信息:";
    m_pChatroom->SendText(m_strName, strTo, strMessage);    // 发送文本
}

void CommonMember::SendImage(const string &strTo, const string &strImage)
{
    qDebug() << "普通会员不能发送图片!";
}

具体同事类 DiamondMember(钻石会员类)

cpp 复制代码
/**
 * @brief 具体同事类 DiamondMember(钻石会员类)
 */
class DiamondMember: public Member
{
public:
    DiamondMember(const string& strName);
    ~DiamondMember() = default;

public:
    void SendText(const string& strTo, const string& strMessage) override;
    void SendImage(const string& strTo, const string& strImage) override;
};

DiamondMember::DiamondMember(const string &strName): Member(strName)
{
    // ...
}

void DiamondMember::SendText(const string &strTo, const string &strMessage)
{
    qDebug() << "钻石会员发送信息:";
    m_pChatroom->SendText(m_strName, strTo, strMessage);    // 发送文本
}

void DiamondMember::SendImage(const string &strTo, const string &strImage)
{
    qDebug() << "钻石会员发送图片:";
    m_pChatroom->SendImage(m_strName, strTo, strImage);    // 发送图片
}

测试函数

cpp 复制代码
/**
 * @brief 测试函数
 */
void ClientTest()
{
    AbstractChatroom* pChatroom = new ChatGroup();

    Member* pMember1 = new DiamondMember("张三");
    Member* pMember2 = new DiamondMember("李四");
    Member* pMember3 = new DiamondMember("王五");
    Member* pMember4 = new CommonMember("小芳");
    Member* pMember5 = new CommonMember("小红");

    pChatroom->Rergister(pMember1);
    pChatroom->Rergister(pMember2);
    pChatroom->Rergister(pMember3);
    pChatroom->Rergister(pMember4);
    pChatroom->Rergister(pMember5);

    pMember1->SendText("李四", "李四,你好!");
    pMember2->SendText("张三", "张三,你好!");
    pMember1->SendText("李四", "今天天气不错,有太阳!");
    pMember2->SendImage("张三", "一个很大很大的太阳!");
    pMember2->SendImage("张三", "太阳");

    pMember3->SendText("小芳", "还有问题吗?");
    pMember3->SendText("小红", "还有问题吗?");

    pMember4->SendText("王五", "没有了,谢谢!");
    pMember5->SendText("小红", "我也没有了!");
    pMember5->SendImage("王五", "谢谢!");

    delete pChatroom;

    delete pMember1;
    delete pMember2;
    delete pMember3;
    delete pMember4;
    delete pMember5;
}

7 思考小结

中介者模式优点:

  • 简化了对象之间的交互
  • 将各同事解耦
  • 减少子类生成

中介者模式的适用场景:

  • 系统中对象之间存在复杂的引用和通信关系,产生的互相依赖关系结构混乱且难以理解。
  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  • 想定制一个分布在多个类中的行为,而又不想生成太多的子类。
相关推荐
崎岖Qiu9 小时前
【设计模式笔记06】:单一职责原则
java·笔记·设计模式·单一职责原则
Yeniden9 小时前
【设计模式】适配器模式大白话讲解!
设计模式·适配器模式
杨筱毅10 小时前
【C++】【常见面试题】最简版带大小和超时限制的LRU缓存实现
c++·面试
陌路2011 小时前
C23构造函数与析构函数
开发语言·c++
_OP_CHEN11 小时前
C++进阶:(二)多态的深度解析
开发语言·c++·多态·抽象类·虚函数·多态的底层原理·多态面试题
金色熊族13 小时前
装饰器模式(c++版)
开发语言·c++·设计模式·装饰器模式
Dream it possible!13 小时前
LeetCode 面试经典 150_链表_旋转链表(64_61_C++_中等)
c++·leetcode·链表·面试
西红柿维生素15 小时前
23种设计模式-框架中的使用
java·开发语言·设计模式
CS创新实验室16 小时前
典型算法题解:长度最小的子数组
数据结构·c++·算法·考研408