首页 > 其他分享 >中介模式

中介模式

时间:2023-04-10 21:12:16浏览次数:30  
标签:mediator void 模式 private 中介 组件 public

概述

《设计模式》一书中对于 “中介模式” 的意图描述如下:

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

具体来讲,就是在对象过多,并且这些对象之间的交互关系过于复杂的情况下,通过引入第三方 “中介” 来处理这些对象之间的交互关系

一般 “中介者模式” 的 UML 图如下所示:

mediator_pattern.png

一般会在以下场景中使用 “中介者模式”:

  • 一组对象以定义良好但复杂的方式进行通信,产生的相互依赖关系结构混乱并且难以理解
  • 一个对象引用其它很多对象并且直接与这些对象进行通信,导致难以复用该对象
  • 想要定制一个分布在多个类中的行为,但是又不想生成太多的子类

具体示例

以一个对话框的交互为例,假设现在有这样的一个对话框,它需要在用户选择相关的字体时自动地将所有的文本输入内容都换成这一类型的字体。同时,也存在一个复选框,需要用户在选择对应的内容后才能提交本次的内容。如果按照传统的开发模式,将这一行为固定在不同的组件类中,这也能达到这个目的,但是这些对象就无法复用了,如果以后需要重新设计一个新的对话框,那么就不得不重新定义相关的子类,这很明显是不可取的

通过中介者模式,我们可以将对话框的处理逻辑交给 Mediator 进行处理,而其它的组件只需要采取相应的行为即可

定义中介者的对象类型:

public interface Mediator {
    void showDialog(); // 显示对话框
    void widgetChanged(Widget widget); // 当存在组件发神改变时需要采取的行为
}

定义每个组件的公共接口 Widget

public interface Widget {
    void onChanged(); // 当部分组件发生变化时需要采取的行为
}

由于这里需要知道中介者的存在,因此我们需要定义一个抽象组件父类来完成这一感知操作:

public abstract class AbstractWidget implements Widget {
    private final Mediator mediator;
    
    public AbstractWidget(Mediator mediator) {
        this.mediator = mediator;
    }
    
    @Override
    public void onChanged() {
        mediator.widgetChanged(this); // 将组件的改变事件委托给中介对象进行处理
    }
}

之后,定义具体的组件来实现相关的组件行为:

// 选择框的具体实例类型
public class ListBox extends AbstractWidget {
    private final Item[] items = new Items[]{};
    private int index; // 当前选择的条目
    
    public ListBost(Mediator mediator) {
        super(mediator);
    }
    
    public Item selected() {
        // 获取当前选择的条目
        return  items[index];
    }
}

// 文本框组件的具体实例类型
public class TextField extends AbstractWidget {
    private String content;
    
    public TextField(Mediator mediator) {
        super(mediator);
    }
    
    public String currentContent() {
        // 获取当前文本框的输入内容
        return content;
    }
    
    public void setContent(String content) {
        this.content = content;
    }
}

// 按钮组件的具体行为
public class Button extends AbstractWidget {
    
    private boolean clickedAble = false;
    
    public Button(Mediator mediator) {
        this.mediator = mediator;
    }
    
    public void click() {
        // 点击按钮时的具体行为
    }
    
    public void setClickedAble(boolean flag) {
        this.clickedAble = flag; // 设置是否可点击
    }
    
    public boolean clickedAble() {
        return this.clickedAble;
    }
}

现在,已经定义了部分具体的组件实例对象,需要定义具体的中介者来协调它们之间的交互关系:

public class SimpleMediator implements Mediator {
    private final ListBox listBox;
    private final TextField textField;
    private final Button button;
    
    public SimpleMediator() {
        this.listBox = new ListBox(this);
        this.textField = new TextField(this);
        this.button = new Button(this);
    }
    
    @Override
    public void showDialog() {
        // 省略组件的布局代码实现
    }
    
    @Override
    public void widgetChanged(Widget widget) {
        if (widget == listBox) {
            this.textField.setContent(listBox.selected().content());
            this.button.setClickedAble(true);
        } else if (widget == TextField) {
            this.textField.setContent(getInput());
        } else {
            if (this.clickedAble()) {
                this.button.click();
            }
        }
    }
}

总结

中介者模式看起来和外观模式很像,这两者的最大区别是外观模式只是对子系统的抽象,为子系统提供了一个更为方便的接口,这个接口是单向的,也就是说,具体内部的组件不需要知道和其它组件的协作关系;而中介者模式则提供了各个组件之间协作行为,这些行为可以是多向的


参考:

[1] 《设计模式—可复用面向对象基础》

标签:mediator,void,模式,private,中介,组件,public
From: https://www.cnblogs.com/FatalFlower/p/17304303.html

相关文章

  • 单例模式
    单例模式单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。即:类在内存中只能存在一个示例对象设计思路:创建的对象肯定是要存入内存的,也就是用户态的那片空间(栈、堆、读写段、只读段),如果直接将类对象的创建放在类的外面,无论放在哪块区域都是行不通......
  • 单例模式
    单例模式单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。即:类在内存中只能存在一个示例对象设计思路:创建的对象肯定是要存入内存的,也就是用户态的那片空间(栈、堆、读写段、只读段),如果直接将类对象的创建放在类的外面,无论放在哪块区域都是行不通......
  • KMP算法(串的模式匹配算法)(未完待续......)
    KMP算法的实现1.基本原理  在暴力破解算法(BF算法)中,模式串需要一个一个来跟主串进行对比,若有一个不相同,则主串前进一位,继续从头开始进行比较,这样比较的最坏时间复杂度为O(mn),例:‘aaaaaaaaab’和‘aaab’,需要比较到最后一个才能成功,效率太过低下。  KMP算法的原理是,找到模式串......
  • VMware网络连接模式
    VMware网络连接模式一、桥接模式1.介绍相当于虚拟机的网卡和宿主机的物理网卡连接到虚拟机所提供的VMnet0虚拟交换机上2.作用虚拟机、宿主机均可访问外网虚拟机、宿主机之间可通信3.操作关闭宿主机和虚拟机防火墙Windows:控制面板-->系统和安全-->WindowsDefender......
  • 【享元设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
    简介享元模式(FlyweightPattern),是一种结构型设计模式。主要用于减少创建对象的数量,以减少内存占用和提高性能。它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。当程序需要生成数量巨大的相似对象时,可能对内存有......
  • AOP底层原理-装饰模式(静态代理)
    原始方法:静态代理的方法:   测试:  ......
  • Docker的网络模式
    1、Docker网络实现原理(1)Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器......
  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一致性的概念......
  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一......
  • 【设计模式25】中介者模式
    基本概念具体案例#include<iostream>#include<vector>#include<string>#include<algorithm>#include<crtdbg.h>#include<unordered_map>usingnamespacestd;classCountry;//联合国机构classUniteNations{public: UniteNations()......