十九、中介者模式

news2024/9/23 15:22:55

文章目录

  • 1 基本介绍
  • 2 案例
    • 2.1 Developer 抽象类
    • 2.2 FrontendDeveloper 类
    • 2.3 BackendDeveloper 类
    • 2.4 Mediator 接口
    • 2.5 ProjectManager 类
    • 2.6 Client 类
    • 2.7 Client 类的运行结果
    • 2.8 总结
  • 3 各角色之间的关系
    • 3.1 角色
      • 3.1.1 Colleague ( 同事 )
      • 3.1.2 ConcreteColleague ( 具体的同事 )
      • 3.1.3 Mediator ( 中介者 )
      • 3.1.4 ConcreteMediator ( 具体的中介者 )
      • 3.1.5 Client ( 客户端 )
    • 3.2 类图
  • 4 注意事项
  • 5 在框架中的使用
  • 6 优缺点
  • 7 适用场景
  • 8 总结


1 基本介绍

中介者模式(Mediator Pattern)是一种 行为型 设计模式,它降低了多个对象和类之间的 通信复杂性,通过引入一个中介对象来 封装 一系列对象之间的 交互使得这些对象不需要直接相互引用

2 案例

本案例让甲方将需求告知项目经理,然后项目经理将需求分发给前、后端开发人员,前、后端开发人员负责根据需求修改各自负责的代码。

2.1 Developer 抽象类

public abstract class Developer { // 开发人员
    // 由于其子类的逻辑十分简单,无需向 mediator 发送消息,所以其子类没有直接使用 mediator
    protected Mediator mediator; // 对应的中介者

    public Developer(Mediator mediator) {
        this.mediator = mediator;
    }

    protected abstract void modifyCode(String require); // 根据需求修改代码
}

2.2 FrontendDeveloper 类

public class FrontendDeveloper extends Developer { // 前端开发人员
    public FrontendDeveloper(Mediator mediator) {
        super(mediator);
    }

    @Override
    protected void modifyCode(String require) {
        System.out.println("前端开发人员根据需求「" + require + "」修改前端显示的代码");
    }
}

2.3 BackendDeveloper 类

public class BackendDeveloper extends Developer { // 后端开发人员
    public BackendDeveloper(Mediator mediator) {
        super(mediator);
    }

    @Override
    protected void modifyCode(String require) {
        System.out.println("后端开发人员根据需求「" + require + "」修改前端显示的代码");
    }
}

2.4 Mediator 接口

// 实现这个接口后,可以当项目的中介者,接收甲方的需求,通知前、后端开发人员修改代码
public interface Mediator {
    void organizeMembers(); // 组织开发组的成员
    void changeRequire(String require); // 甲方更改需求
}

2.5 ProjectManager 类

public class ProjectManager implements Mediator { // 项目经理
    // 假设项目中只需要一个前端开发人员和一个后端开发人员
    private FrontendDeveloper frontendDeveloper;
    private BackendDeveloper backendDeveloper;

    @Override
    public void organizeMembers() {
        // 组织了两个开发人员进行开发
        frontendDeveloper = new FrontendDeveloper(this);
        backendDeveloper = new BackendDeveloper(this);
    }

    @Override
    public void changeRequire(String require) {
        System.out.println("项目经理收到甲方更改的需求「" + require + "」");
        frontendDeveloper.modifyCode(require);
        backendDeveloper.modifyCode(require);
    }
}

2.6 Client 类

public class Client { // 客户端,充当甲方,测试了项目经理更改需求的能力
    public static void main(String[] args) {
        Mediator pm = new ProjectManager();
        pm.organizeMembers();

        pm.changeRequire("增加一个 傻瓜式引导 的功能");
        pm.changeRequire("增加一个 个性化内容推荐 的功能");
    }
}

2.7 Client 类的运行结果

项目经理收到甲方更改的需求「增加一个 傻瓜式引导 的功能」
前端开发人员根据需求「增加一个 傻瓜式引导 的功能」修改前端显示的代码
后端开发人员根据需求「增加一个 傻瓜式引导 的功能」修改前端显示的代码
项目经理收到甲方更改的需求「增加一个 个性化内容推荐 的功能」
前端开发人员根据需求「增加一个 个性化内容推荐 的功能」修改前端显示的代码
后端开发人员根据需求「增加一个 个性化内容推荐 的功能」修改前端显示的代码

2.8 总结

在本案例中,甲方更改需求时,只需要通知项目经理即可,无需通知具体的开发人员,通知具体开发人员的任务由项目经理完成。此外,前后端开发人员员也不需要向对方提问应该如何达成需求,由项目经理来通知他们应该达成什么样的需求。这样就减少了对象之间的交流,只存在必要的交流,简化了对象之间的关系。

3 各角色之间的关系

3.1 角色

3.1.1 Colleague ( 同事 )

该角色负责 定义与 Mediator 角色进行通信的 接口。本案例中,Developer 抽象类扮演了该角色。

3.1.2 ConcreteColleague ( 具体的同事 )

该角色负责 实现 Colleague 角色定义的 接口。本案例中,FrontendDeveloper, BackendDeveloper 类都在扮演该角色。

3.1.3 Mediator ( 中介者 )

该角色负责 定义 创建 ConcreteColleague 角色的 接口 和 与其进行通信的 接口。本案例中,Mediator 接口扮演了该角色。

3.1.4 ConcreteMediator ( 具体的中介者 )

该角色负责 实现 Mediator 角色的接口。本案例中,ProjectManager 类扮演了该角色。

3.1.5 Client ( 客户端 )

该角色负责 创建 ConcreteMediator 角色的对象,并 使用它完成具体的业务逻辑。本案例中,Client 类扮演了该角色。

3.2 类图

alt text
说明:

  • Colleague 中的 controlColleague() 方法用于与 Mediator 通信,根据 Mediator 的指示修改自己的状态。
  • Mediator 可以是接口。
  • Colleague 也可以是接口,不过需要将其聚合的 Mediator 放到所有 ConcreteColleague 中。
  • 当 Colleague 是抽象类时,其 setMediator() 方法可以由构造器替换。

4 注意事项

  • 中介者责任重大:中介者对象承担了较多的责任,它是所有对象之间通信的桥梁。因此,一旦中介者出现了问题,整个系统就可能受到影响。所以,在设计中介者时,需要确保其 稳定性可靠性
  • 避免中介者对象复杂化:如果设计不当,中介者对象可能会变得过于复杂,难以理解和维护。在实际使用中,需要 特别注意中介者的设计避免其承担过多的责任和功能。可以通过合理划分中介者的职责、采用模块化设计等方法来降低其复杂度。
  • 系统灵活性的保持:虽然中介者模式提高了系统的灵活性,但 在设计时需要确保系统仍然能够应对未来的变化。例如,可以通过定义 可扩展的中介者接口、使用 策略模式 等方法来增强系统的可扩展性。
  • 性能考虑:在某些情况下,通过中介者进行 间接交互 可能比 直接交互 具有更高的性能开销。因此,在设计完成后,需要对系统的性能进行测试,并根据测试结果进行优化。例如,可以通过优化中介者的内部实现、减少不必要的通信等方法来提高系统性能。

5 在框架中的使用

在流行的 Java 框架中,使用了中介者模式的思想:

  • MVC 框架:在 MVC(Model-View-Controller)框架 中,控制器(Controller)充当了 模型(Model)和 视图(View)之间的中介者。控制器负责接收用户的输入,并将其转换为模型可以理解的格式,同时,当模型状态发生变化时,控制器也会负责通知视图进行更新。这种设计使得模型、视图和控制器之间的耦合度降低,提高了系统的可维护性和可扩展性。
  • 消息中间件:在分布式系统中,消息中间件(如 RabbitMQ、Kafka 等)也体现了中介者模式的思想。消息中间件 作为消息的 生产者消费者 之间的中介,负责消息的存储和转发,使得生产者和消费者之间不需要直接进行通信,从而降低了系统的耦合度,提高了系统的可靠性和可扩展性。

6 优缺点

优点

  • 解耦与结构转换多个类相互耦合 容易形成 网状结构,复杂且难以维护。使用中介者模式可以将 网状结构 分离为 星型结构,通过中介者对象进行通信,从而实现解耦。
  • 符合迪米特法则(降低对象间的耦合度):中介者模式使得 对象之间不需要知道彼此的具体实现细节,只需通过中介者进行通信,这符合 迪米特法则,有助于减少对象之间的 耦合度。这使得对象之间的依赖关系更加简单,系统的结构更加清晰。
  • 易于扩展和维护:当系统中需要增加新的对象或改变对象之间的交互方式时,只需修改中介者对象即可,而无需修改其他对象,这降低了系统 扩展维护 的复杂性。
  • 提高系统的灵活性:通过更换不同的中介者对象,可以灵活地改变对象之间的交互逻辑,从而增加系统的 灵活性

缺点

  • 中介者可能变得复杂:如果系统中存在大量的对象,并且这些对象之间的交互关系非常复杂,那么中介者对象可能会变得非常庞大和复杂。这会增加中介者对象的维护难度,并可能导致代码难以理解和修改。
  • 对中介者的依赖:由于 所有对象之间的交互都通过中介者进行,因此 系统对中介者的依赖程度较高。如果中介者出现故障或设计不当,可能会影响整个系统的正常运行。
  • 可能隐藏系统复杂性:中介者模式可能会 隐藏对象之间的 直接交互关系,使得系统的整体结构和交互逻辑变得不够直观。这可能会给开发人员带来一定的理解难度,尤其是在处理复杂的系统时。
  • 更高的性能开销:在某些情况下,通过中介者进行 间接交互 可能比 直接交互 具有 更高的性能开销。虽然这种开销在大多数情况下是可以接受的,但在性能敏感的应用中可能需要谨慎考虑。

7 适用场景

  • 引用关系复杂的系统
    • 系统中对象之间存在复杂的引用关系,且 这些引用关系导致系统结构混乱、难以理解 时,可以考虑使用中介者模式。通过引入中介者对象,可以封装对象之间的交互细节,降低系统的复杂度。
    • 例如,在 电商平台 中,卖家、买家、物流公司和支付平台之间可能存在复杂的交互关系,可以通过增加一个“消费中介”来分离它们之间的关系。
  • 需要改变行为的系统
    • 如果 系统中对象之间的交互行为需要频繁变更,且 这些变更会影响到多个对象 时,可以使用中介者模式。通过增加新的中介者类,可以轻松地实现行为的扩展和变更,而无需修改原有对象。
    • 例如,在 多人聊天室场景 中,如果需要变更消息的传递方式(如从文本消息变为语音消息),可以通过增加一个新的中介者类来实现,而无需修改用户对象。
  • 高耦合的系统
    • 系统中对象之间的耦合度较高,且 这种耦合度影响了系统的可维护性和可扩展性 时,可以考虑使用中介者模式。通过中介者对象来封装对象之间的交互,可以降低对象之间的耦合度,使系统更加灵活和易于维护。
    • 例如,在 MVC 框架中,控制器(Controller)作为模型(Model)和视图(View)之间的中介者,降低了它们之间的耦合度。当需要修改视图或模型的实现时,只需修改控制器即可,而无需修改其他组件。
  • 集中化交互管理的系统
    • 在某些场景中,可能 需要一个中心化的对象来管理多个对象之间的交互。此时,可以使用中介者模式来实现。中介者对象负责接收来自各个对象的请求,并根据一定的规则将这些请求转发给相应的对象进行处理。
    • 例如,在交通控制系统中,交通灯可以作为中介者对象来管理车辆和行人的交互。交通灯根据当前的道路情况和交通规则来控制车辆和行人的通行。

8 总结

中介者模式 是一种 行为型 设计模式,它通过引入 中介,组织了系统中各个对象之间的关系,从 网状关系 简化到 星型关系,降低了系统的耦合度,提高了系统的灵活性。不过,给对象之间添加一个中介会导致性能的下降,如果对性能要求很高,最好不要使用本模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ-消息队列-centos7

一、RabbitMQ安装 1、通过官网下 官网网址:https://www.rabbitmq.com 首先下载erlang-23.3.4.11-1.el7.x86_64.rpm,其次下载rabbitmq-server-3.10.0-1.el7.noarch.rpm 注意:RabbitMQ是由erlang开发的,所以必须先安装erlang版本…

Pytorch1: Anaconda下载,安装,配置

Anaconda手册 一,Anconada1,Anconada简介 二、下载、安装、配置环境变量1,安装 三、anaconda创建多版本python环境四、anaconda 安装 pytorch五、Jupyter Notebook 一,Anconada 1,Anconada简介 Anaconda就是一个用于…

【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch

JUC:java.util.concurrent 一、Callable 接⼝ 接口方法Callablecall,带有返回值Runnablerun,void所以创建一个线程,希望它给你返回一个结果,那么使用 Callable 更加方便一些 比如,创建一个线程&#xff…

leetcode350. 两个数组的交集 II,哈希表

leetcode350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可…

导出word格式的Javadoc(可用于快速生成项目详细设计文档)

导出word格式的Javadoc ​ 最近要编写项目详细设计文档,作为程序员当然想看看有没有能够自动生成的办法,生成详细设计文档,然后再在生成的基础上略做修改就好了(偷懒大法~),还真有,特此分享&am…

数字乡村+智慧农业数字化转型大数据平台建设方案

1. 数字农业发展趋势 数字农业正经历全环节数字技术应用、全流程生产经营再造、全方位线上线下对接和管理服务全生命周期覆盖的四大趋势,标志着我国农业进入高质量发展新阶段。 2. 数字乡村的战略意义 数字乡村作为数字化、网络化和信息化的产物,对于…

人工智能技术工程师由谁颁发?都学习哪些课程?

人工智能技术工程师是一个充满挑战和机遇的职业。他们将用自己的专业知识和技能,为人类带来更加美好的未来。 一、人工智能工程师发证单位是谁? 人工智能技术工程师证书是由工业和信息化部教育与考试中心颁发的。 工信部电子标准院的人工智能从业人员认…

基于飞腾平台的Hadoop的安装配置

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力,聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域,包含了应用使能套件、软件仓库、软件支持、软件适…

旅游卡真伪一招辨别,避免旅行陷阱!

揭秘旅游卡真伪!一招教你识别隐藏陷阱,避免旅行大坑! 对于热爱旅行的朋友们来说,旅游卡无疑是一种方便又实惠的选择。 然而,随着市场上的旅游卡种类越来越多,如何选择一张真实有效的旅游卡成为了大家关注…

CI/CD 自动化:最大限度地提高极狐GitLab 群组的“部署冻结”影响

极狐GitLab 是 GitLab 在中国的发行版,专门面向中国程序员和企业提供企业级一体化 DevOps 平台,用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规,而且所有的操作都是在一个平台上进行,省事省心省钱。可以一键安装极狐GitL…

矩阵获客时代,如何有效管理云微客短视频矩阵?

随着短视频内容数量的快速增长,一站式、高效、智能化的矩阵管理模式,正逐渐受到各个行业的关注和喜爱。那么该如何有效地管理短视频矩阵,确保内容的高质量、高效率和准确投放呢? 当今数字化时代,短视频已经成为了一种极…

Oracle 用户-表空间-表之间关系常用SQL

问题: 当某一个表数据量特别大,突然插入数据一直失败,可能是表空间不足,需要查看表的使用率 用户-表空间-表之间关系:用户可以有多个表空间,表空间可以有多个表,表只能拥有一个表空间和用户 1.…

联邦学习:破解农业大数据共享的安全难题

( 于景鑫 国家农业信息化工程技术研究中心 )农业大数据是农业智能化的基石,其共享与开放是发掘数据价值、驱动农业变革的关键。然而,数据隐私与安全问题如同数据共享之路上的一道坎,牵制着农业大数据的流动与融合。联邦学习作为一种颠覆性的分布式机器学…

1Panel应用推荐:Bytebase开源数据库DevOps解决方案

1Panel(github.com/1Panel-dev/1Panel)是一款现代化、开源的Linux服务器运维管理面板,它致力于通过开源的方式,帮助用户简化建站与运维管理流程。为了方便广大用户快捷安装部署相关软件应用,1Panel特别开通应用商店&am…

技术爱好者完全用台式机部件定制游戏笔记本电脑

高端笔记本电脑的功能强大到令人难以置信的地步,但大多数笔记本电脑在至少几个关键性能方面仍然落后于台式机。一位 YouTuber 对这种情况感到厌倦,为了抹除这种差距,他开始了为期 14 个月的旅程,使用真正的台式机硬件打造自己的笔…

基于R语言遥感随机森林建模与空间预测;遥感数据处理与特征提取;数据分析与可视化

目录 第一章 理论基础与数据准备【夯实基础】 第二章 随机森林建模与预测【讲解实践】 第三章 实践案例与项目 更多应用 随机森林作为一种集成学习方法,在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性,随…

ubuntu 24.04 软件源配置,替换为国内源

ubuntu 默认的官网源下载速度非常慢,新装 ubuntu 系统首先把 apt 软件源替换成国内源。 1、使用软件和更新设置国内源 打开软件和更新,选择位于中国的服务器: 外链图片转存失败,源站可能有防盗链机制,建议将图片保存…

JavaEE 第11节 定时器

前言 本篇博客重点介绍定时器的简单实现,帮助理解其底层原理。关于JAVA工具类自带的定时器,只会简单介绍,详细使用参阅官方文档(下文中有官方文档的连接)。 一、什么是定时器 定时器的概念非常简单。 它在软件开发…

Umi-OCR 图片文字智能识别软件,不需联网,Linux 下运行错误修复,AI 识文一文搞定!

Umi-OCR 图片文字智能识别软件,不需联网,Linux 下运行除错修复,AI 识文一文搞定! Umi-OCR 是一款开源的图片文字只能识别软件,支持多国语言识别,支持截图OCR / 批量OCR / PDF识别 / 二维码 / 公式识别。 …

C:数组传参的本质

1、一维数组传参的本质 数组传参是指在函数调用时将数组作为参数传递给函数。 int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;}数组传参只需要写数组名就可以了。注意:数组名是arr,而不是arr[10] 数组传参形参该怎么写呢&am…