设计模式:中介者模式 Mediator

目录


前言

中介者是一种行为设计模式,能让你减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作。


问题

假如你有一个创建和修改客户资料的对话框, 它由各种控件组成, 例如 文本框(TextField)、复选框(Checkbox) 和 按钮(Button)等。

某些表单元素可能会直接进行互动。 例如, 选中"我有一只狗"复选框后可能会显示一个隐藏文本框用于输入狗狗的名字。 另一个例子是提交按钮必须在保存数据前校验所有输入内容。

如果直接在表单元素代码中实现业务逻辑, 你将很难在程序其他表单中复用这些元素类。 例如, 由于复选框类与狗狗的文本框相耦合, 所以将无法在其他表单中使用它。 你要么使用渲染资料表单时用到的所有类,要么一个都不用。

解决方案

中介者模式建议你停止组件之间的直接交流并使其相互独立。这些组件必须调用特殊的中介者对象, 通过中介者对象重定向调用行为,以间接的方式进行合作。最终,组件仅依赖于一个中介者类,无需与多个其他组件相耦合。

在资料编辑表单的例子中, 对话框(Dialog) 类本身将作为中介者, 其很可能已知自己所有的子元素, 因此你甚至无需在该类中引入新的依赖关系。

绝大部分重要的修改都在实际表单元素中进行。 让我们想想提交按钮。之前,当用户点击按钮后,它必须对所有表单元素数值进行校验。 而现在它的唯一工作是将点击事件通知给对话框。 收到通知后, 对话框可以自行校验数值或将任务委派给各元素。 这样一来, 按钮不再与多个表单元素相关联,而仅依赖于对话框类。

你还可以为所有类型的对话框抽取通用接口, 进一步削弱其依赖性。 接口中将声明一个所有表单元素都能使用的通知方法, 可用于将元素中发生的事件通知给对话框。 这样一来,所有实现了该接口的对话框都能使用这个提交按钮了。

采用这种方式, 中介者模式让你能在单个中介者对象中封装多个对象间的复杂关系网。 类所拥有的依赖关系越少, 就越易于修改、扩展或复用。

结构

代码

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>
#include <map>
using namespace std;

class AbstractComponent{
public:
    virtual void operation()=0;
    virtual ~AbstractComponent(){}
};

class AbstractMediator{
public:
    virtual void notify(const string& sender)=0;
    virtual void addComponent(const string& name,shared_ptr<AbstractComponent> component)=0;
    virtual ~AbstractMediator(){}
};
class Dialog:public AbstractMediator{
public:
    void notify(const string& sender) override {
        if (sender == "button") {
            // 当按钮被触发时,协调复选框也执行操作
            cout << "中介者:按钮被按下,触发复选框操作" << endl;
            if (m_component.find("checkbox") != m_component.end()) {
                m_component["checkbox"]->operation();
            }
        } else if (sender == "checkbox") {
            cout<<"end"<<endl;
        }
    }
    void addComponent(const string& name,shared_ptr<AbstractComponent> component){
        m_component.insert(make_pair(name,component));
    }
private:
    map<string,shared_ptr<AbstractComponent>> m_component;
};

class Button:public AbstractComponent{
public:
    Button(shared_ptr<AbstractMediator> mediator){m=mediator;}
    void operation() override {
        cout << "按钮被按下" << endl;
        // 自身状态变化后,通过中介者通知其他组件
        m->notify("button"); 
    }
private:
    shared_ptr<AbstractMediator> m;
};
class Checkbox:public AbstractComponent{
public:
    Checkbox(shared_ptr<AbstractMediator> mediator){m=mediator;}
    void operation() override{
        cout << "调用复选框" << endl;
        // 自身状态变化后,通过中介者通知其他组件
        m->notify("checkbox"); 
    }
private:
    shared_ptr<AbstractMediator> m;
};

int main(){
    auto dialog=make_shared<Dialog>();
    auto button=make_shared<Button>(dialog);
    auto checkbox=make_shared<Checkbox>(dialog);

    dialog->addComponent("button",button);
    dialog->addComponent("checkbox",checkbox);
    
    button->operation();
    cout<<"----------------"<<endl;
    checkbox->operation();

    return 0;
}
相关推荐
源代码•宸29 分钟前
深入浅出设计模式——创建型模式之原型模式 Prototype
c++·经验分享·设计模式·原型模式
小钻风33663 小时前
设计模式之单例模式及其在多线程下的使用
单例模式·设计模式
liulilittle6 小时前
备忘录设计模式 vs 版本设计模式
开发语言·c++·算法·设计模式
困鲲鲲7 小时前
设计模式:组合模式 Composite
设计模式·组合模式
使一颗心免于哀伤8 小时前
《设计模式之禅》笔记摘录 - 11.策略模式
笔记·设计模式
困鲲鲲1 天前
设计模式:状态模式 State
设计模式·状态模式
蝸牛ちゃん1 天前
设计模式(十一)结构型:外观模式详解
设计模式·系统架构·软考高级·外观模式
weixin_470880261 天前
设计模式实战:自定义SpringIOC(亲手实践)
设计模式·面试·个人提升·springioc·设计模式实战·spring框架原理
阳光明媚sunny1 天前
创建型设计模式-工厂方法模式和抽象工厂方法模式
设计模式·工厂方法模式