《设计模式的艺术》笔记 - 中介者模式

介绍

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

实现

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class Mediator;
class Colleague {   // 抽象同事类
public:
    Colleague(Mediator *mMediator);
    virtual void method1() = 0; // 处理自己的行为
    virtual void method2() = 0; // 与中介者进行通讯
protected:
    Mediator *m_mediator;
};

class Mediator {    // 抽象中介者;
public:
    void registerColleague(Colleague *colleague);

    virtual void operation(Colleague *colleague) = 0;

protected:
    std::vector<Colleague *> m_colleagues;
};

class ConcreteMediator : public Mediator {  // 具体中介者
public:
    void operation(Colleague *colleague) override;
};

class ConcreteColleagueA : public Colleague {    // 具体同事类A
public:
    ConcreteColleagueA(Mediator *mediator);
    void method1() override;

    void method2() override;
};

class ConcreteColleagueB : public Colleague {    // 具体同事类B
public:
    ConcreteColleagueB(Mediator *mediator);
    void method1() override;

    void method2() override;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Colleague::Colleague(Mediator *mMediator) : m_mediator(mMediator) {

}

void Mediator::registerColleague(Colleague *colleague) {
    if (colleague) {
        m_colleagues.push_back(colleague);
    }
}

void ConcreteMediator::operation(Colleague *colleague) {
    for (auto &c : m_colleagues) {
        if (c != colleague) {
            c->method1();
        }
    }
}

ConcreteColleagueA::ConcreteColleagueA(Mediator *mediator) : Colleague(mediator){

}

void ConcreteColleagueA::method1() {
    std::cout << "ConcreteColleagueA处理自身逻辑" << std::endl;
}

void ConcreteColleagueA::method2() {
    std::cout << "ConcreteColleagueA通知中介者" << std::endl;
    if (m_mediator) {
        m_mediator->operation(this);
    }
}

ConcreteColleagueB::ConcreteColleagueB(Mediator *mediator) : Colleague(mediator){

}

void ConcreteColleagueB::method1() {
    std::cout << "ConcreteColleagueB处理自身逻辑" << std::endl;
}

void ConcreteColleagueB::method2() {
    std::cout << "ConcreteColleagueB通知中介者" << std::endl;
    if (m_mediator) {
        m_mediator->operation(this);
    }
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Mediator *mediator = new ConcreteMediator();
    Colleague *colleagueA = new ConcreteColleagueA(mediator);
    Colleague *colleagueB = new ConcreteColleagueB(mediator);
    mediator->registerColleague(colleagueA);
    mediator->registerColleague(colleagueB);
    colleagueA->method2();
    colleagueB->method2();
    delete colleagueA;
    delete colleagueB;
    delete mediator;
    return 0;
}

总结

优点

  1. 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互。一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星形结构。

  2. 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,可以独立地改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合开闭原则。

  3. 可以减少大量同事子类生成。中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需要生成新的中介者子类即可,这使得各个同事类可以被重用,无须对同事类进行扩展。

缺点

  1. 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

适用场景

  1. 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。

  2. 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。

  3. 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。

练习

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class Mediator;
class Pane {   // 抽象同事类
public:
    Pane(const std::string &name, Mediator *mediator);
    virtual void update() = 0; // 处理自己的行为
    virtual void tellOther() = 0; // 与中介者进行通讯
protected:
    Mediator *m_mediator;
    std::string m_name;
};

class Mediator {    // 抽象中介者;
public:
    void registerPane(Pane *pane);

    virtual void operation(Pane *pane) = 0;

protected:
    std::vector<Pane *> m_panes;
};

class Window : public Mediator {  // 具体中介者
public:
    void operation(Pane *pane) override;
};

class TextPane : public Pane {    // 具体同事类TextPane
public:
    TextPane(const std::string &name, Mediator *mediator);
    void update() override;

    void tellOther() override;
};

class ListPane : public Pane {    // 具体同事类ListPane
public:
    ListPane(const std::string &name, Mediator *mediator);
    void update() override;

    void tellOther() override;
};

class GraphicPane : public Pane {    // 具体同事类GraphicPane
public:
    GraphicPane(const std::string &name, Mediator *mediator);
    void update() override;

    void tellOther() override;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Pane::Pane(const std::string &name, Mediator *mediator) : m_name(name), m_mediator(mediator) {

}

void Mediator::registerPane(Pane *pane) {
    if (pane) {
        m_panes.push_back(pane);
    }
}

void Window::operation(Pane *pane) {
    for (auto &c : m_panes) {
        if (c != pane) {
            c->update();
        }
    }
}

TextPane::TextPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){

}

void TextPane::update() {
    std::cout << m_name << "更新显示" << std::endl;
}

void TextPane::tellOther() {
    std::cout << m_name << "通知Window" << std::endl;
    if (m_mediator) {
        m_mediator->operation(this);
    }
}

ListPane::ListPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){

}

void ListPane::update() {
    std::cout << m_name << "更新显示" << std::endl;
}

void ListPane::tellOther() {
    std::cout << m_name << "通知Window" << std::endl;
    if (m_mediator) {
        m_mediator->operation(this);
    }
}

GraphicPane::GraphicPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){

}

void GraphicPane::update() {
    std::cout << m_name << "更新显示" << std::endl;
}

void GraphicPane::tellOther() {
    std::cout << m_name << "通知Window" << std::endl;
    if (m_mediator) {
        m_mediator->operation(this);
    }
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Mediator *mediator = new Window();
    Pane *text = new TextPane("text", mediator);
    Pane *list = new ListPane("list", mediator);
    Pane *graphic = new ListPane("graphic", mediator);
    mediator->registerPane(text);
    mediator->registerPane(list);
    mediator->registerPane(graphic);
    std::cout << "-------------------------" << std::endl;
    text->tellOther();
    std::cout << "-------------------------" << std::endl;
    list->tellOther();
    std::cout << "-------------------------" << std::endl;
    graphic->tellOther();
    std::cout << "-------------------------" << std::endl;

    delete text;
    delete list;
    delete graphic;
    delete mediator;
    return 0;
}
相关推荐
tianchang2 小时前
SSR 深度解析:从原理到实践的完整指南
前端·vue.js·设计模式
饕餮争锋2 小时前
设计模式笔记_创建型_建造者模式
笔记·设计模式·建造者模式
萝卜青今天也要开心3 小时前
2025年上半年软件设计师考后分享
笔记·学习
吃货界的硬件攻城狮3 小时前
【STM32 学习笔记】SPI通信协议
笔记·stm32·学习
蓝染yy4 小时前
Apache
笔记
小小寂寞的城4 小时前
JAVA策略模式demo【设计模式系列】
java·设计模式·策略模式
lxiaoj1114 小时前
Python文件操作笔记
笔记·python
半导体守望者5 小时前
ADVANTEST R4131 SPECTRUM ANALYZER 光谱分析仪
经验分享·笔记·功能测试·自动化·制造
一块plus5 小时前
深度详解 Revive 和 Precompile 技术路径
后端·设计模式·架构
啊我不会诶6 小时前
倍增法和ST算法 个人学习笔记&代码
笔记·学习·算法