设计模式:中介者模式 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;
}
相关推荐
Asort3 小时前
JavaScript设计模式(二十)——状态模式 (State):复杂状态管理的优雅解决方案
前端·javascript·设计模式
紫荆鱼4 小时前
设计模式-备忘录模式(Memento)
c++·后端·设计模式·备忘录模式
wyzqhhhh1 天前
前端常见的设计模式
前端·设计模式
m0_748233641 天前
C++开发中的常用设计模式:深入解析与应用场景
javascript·c++·设计模式
Wind哥1 天前
设计模式23种-C++实现
开发语言·c++·windows·设计模式
闲人编程1 天前
Python设计模式实战:用Pythonic的方式实现单例、工厂模式
开发语言·python·单例模式·设计模式·工厂模式·codecapsule·pythonic
御承扬2 天前
编程素养提升之EffectivePython(Builder篇)
python·设计模式·1024程序员节
杯莫停丶2 天前
设计模式之:享元模式
java·设计模式·享元模式
杯莫停丶2 天前
设计模式之:组合模式
设计模式·组合模式
Hero | 柒2 天前
设计模式之建造者模式
java·设计模式·1024程序员节