化繁为简:中介者模式如何管理复杂对象交互

化繁为简:中介者模式如何管理复杂对象交互

中介者模式 是一种行为型设计模式,定义了一个中介者对象,来封装一组对象之间的交互。中介者模式通过将对象之间的交互行为从多个对象中抽离出来,集中封装在一个中介者对象中,从而使各个对象之间的耦合松散,且可以独立地改变它们之间的交互。

核心思想

中介者模式通过引入一个中介者,协调多个对象之间的交互,避免对象之间的直接通信,从而减少对象之间的耦合

中介者模式的组成角色

Mediator(中介者接口)

  • 中介者定义了对象之间交互的接口,负责协调各个对象之间的通信行为。

ConcreteMediator(具体中介者)

  • 实现了 Mediator 接口,协调各具体同事对象之间的交互。它了解所有的同事对象,并通过其实现交互逻辑。

Colleague(同事类)

  • 每个同事对象只知道中介者,不能直接与其他同事对象通信。所有的交互都通过中介者来完成。

ConcreteColleague(具体同事类)

  • 实现了 Colleague 接口,依赖中介者与其他同事对象通信。每个具体同事对象的行为受到中介者的约束。

中介者模式的 UML 类图

在这里插入图片描述

类图解释

  1. Mediator(中介者接口):定义了同事对象之间的通信接口,通常定义 send() 方法来协调通信。
  2. ConcreteMediator(具体中介者)
    • 实现了 Mediator 接口,具体负责管理和协调同事对象之间的通信。它知道所有的具体同事对象,并通过 send() 方法传递消息或协调操作。
    • 它也可以持有具体的同事对象的引用,负责管理这些对象。
  3. Colleague(同事类):抽象类或接口,每个同事对象依赖中介者与其他同事进行交互。它不直接与其他同事对象通信,而是通过中介者通信。
  4. ConcreteColleague1、ConcreteColleague2(具体同事类):实现 Colleague,定义各自的具体操作。同事对象通过中介者协调相互间的通信

工作原理

  1. 集中通信:中介者模式通过引入 Mediator,将多个对象之间的交互逻辑集中到中介者中,使得各个同事类之间的关系变得松散耦合。
  2. 消息传递:同事对象通过调用中介者的 send() 方法进行通信。中介者负责接收和转发消息,并协调其他同事对象的行为。
  3. 解耦同事对象:同事对象之间不直接交互,而是通过中介者来处理。这样一来,各个对象之间的依赖关系被削弱了。

案例:机场塔台与飞机的调度

场景说明

在机场,飞机起飞和降落的调度是一个非常复杂的过程。如果每架飞机都直接与其他飞机进行通信,会导致混乱并增加空中事故的风险。因此,机场有一个控制塔(塔台),它负责协调所有飞机的起飞和降落

控制塔是中介者,飞机之间的所有通信都必须通过控制塔进行。飞机通过塔台来获取是否可以起飞或降落,从而避免与其他飞机发生冲突。

中介者模式的角色在机场塔台场景中的映射:

  1. Mediator(中介者接口):机场控制塔,负责协调所有飞机的起飞和降落。
  2. ConcreteMediator(具体中介者):具体实现的控制塔,协调飞机的飞行状态。
  3. Colleague(同事类):抽象飞机类,代表参与通信的对象(飞机)。
  4. ConcreteColleague(具体同事类):具体的飞机类,通过控制塔来决定起飞或降落。

在这里插入图片描述

代码实现:机场塔台调度系统

Step 1: 定义中介者接口

中介者接口定义了调度方法,用于协调飞机之间的通信。

// 中介者接口:塔台
public interface Mediator {void notify(String message, Airplane airplane);
}

Step 2: 实现具体的中介者

ControlTower 类是具体的中介者,它负责接收飞机的状态并通知其他飞机,确保起飞和降落顺序的安全。

import java.util.ArrayList;
import java.util.List;// 具体中介者:控制塔
public class ControlTower implements Mediator {private List<Airplane> airplanes;public ControlTower() {this.airplanes = new ArrayList<>();}public void registerAirplane(Airplane airplane) {airplanes.add(airplane);}@Overridepublic void notify(String message, Airplane airplane) {for (Airplane a : airplanes) {if (a != airplane) {a.receive(message);  // 通知其他飞机}}}
}

Step 3: 定义飞机抽象类

飞机类通过中介者来发送和接收信息,而不直接与其他飞机通信。

// 飞机抽象类
public abstract class Airplane {protected Mediator mediator;protected String name;public Airplane(Mediator mediator, String name) {this.mediator = mediator;this.name = name;}public abstract void send(String message);public abstract void receive(String message);
}

Step 4: 实现具体飞机类

具体飞机类实现了 send()receive() 方法,通过塔台来发送和接收消息。

Boeing737 类

// 具体飞机:Boeing 737
public class Boeing737 extends Airplane {public Boeing737(Mediator mediator, String name) {super(mediator, name);}@Overridepublic void send(String message) {System.out.println(this.name + " sends message: " + message);mediator.notify(message, this);  // 通过塔台发送消息}@Overridepublic void receive(String message) {System.out.println(this.name + " receives message: " + message);}
}

AirbusA320 类

// 具体飞机:Airbus A320
public class AirbusA320 extends Airplane {public AirbusA320(Mediator mediator, String name) {super(mediator, name);}@Overridepublic void send(String message) {System.out.println(this.name + " sends message: " + message);mediator.notify(message, this);  // 通过塔台发送消息}@Overridepublic void receive(String message) {System.out.println(this.name + " receives message: " + message);}
}

Step 5: 测试中介者模式

通过 ControlTower 来协调 Boeing737AirbusA320 之间的通信,确保飞机的起飞和降落顺序。

public class MediatorPatternDemo {public static void main(String[] args) {// 创建控制塔ControlTower tower = new ControlTower();// 创建飞机并注册到塔台Airplane boeing737 = new Boeing737(tower, "Boeing 737");Airplane airbusA320 = new AirbusA320(tower, "Airbus A320");tower.registerAirplane(boeing737);tower.registerAirplane(airbusA320);// 飞机发送消息boeing737.send("Requesting permission to land.");airbusA320.send("Requesting permission to take off.");}
}

输出结果

Boeing 737 sends message: Requesting permission to land.
Airbus A320 receives message: Requesting permission to land.
Airbus A320 sends message: Requesting permission to take off.
Boeing 737 receives message: Requesting permission to take off.

中介者模式在机场塔台场景中的工作原理

  1. 集中通信:所有的飞机(同事类)不直接通信,而是通过控制塔(中介者)进行协调。每架飞机都通过塔台发送和接收消息。
  2. 消息传递:当一架飞机发送起飞或降落请求时,塔台负责通知其他飞机,并保证飞行安全和秩序。
  3. 降低耦合性:飞机之间不直接通信,所有交互通过塔台完成,从而降低了飞机之间的耦合,增强了系统的灵活性和扩展性。

SpringMVC 中的 应用

Spring Framework 中,DispatcherServlet 作为前端控制器,实际上也承担了类似于中介者的作用。它在 Spring MVC 架构中负责协调不同组件(如控制器、视图解析器和处理器)的交互。

原理
  • DispatcherServlet 作为一个统一的请求分发器,负责接收 HTTP 请求,并根据请求的 URL 或其他条件,将请求分发给适当的处理器(如 @Controller 的方法)。它并不直接参与具体的请求处理,而是协调多个组件来完成请求-响应的流程。
  • 控制器、视图解析器、处理器等组件之间不直接通信,而是通过 DispatcherServlet 进行交互。
// DispatcherServlet 伪代码,简化示例
public class DispatcherServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 根据请求查找对应的控制器Handler handler = getHandler(request);// 调用控制器处理请求ModelAndView mv = handler.handleRequest(request, response);// 解析视图并返回响应render(mv, response);}
}

在这里,DispatcherServlet 类似于中介者,协调多个组件之间的交互,不同的控制器和视图解析器不直接互相通信,而是通过 DispatcherServlet 进行处理。

中介者模式的优缺点与应用场景总结

优点:

  1. 降低对象之间的耦合性
    • 中介者模式通过引入中介者,使多个对象之间的依赖关系转变为与中介者的依赖,减少了对象之间的直接交互,降低了系统的耦合度。
  2. 简化对象之间的通信
    • 所有通信都通过中介者集中管理,使得系统结构更加清晰,逻辑集中,尤其在多方通信的复杂系统中,简化了交互逻辑。
  3. 符合开闭原则
    • 中介者模式可以方便地扩展或修改交互逻辑,而不影响各个同事对象。可以通过修改中介者来增加或调整各对象之间的交互。
  4. 提高系统的灵活性
    • 当需要增加新的对象或修改对象之间的交互行为时,可以通过中介者进行控制,增强了系统的扩展性和灵活性。

缺点:

  1. 中介者可能变得复杂
    • 随着系统中同事对象的增多,中介者需要处理的交互逻辑也会变得越来越复杂,可能导致中介者变得难以维护,形成一个“上帝对象”。
  2. 不适合简单场景
    • 如果对象之间的交互非常简单,使用中介者模式会引入不必要的复杂性,增加维护成本。

应用场景:

  1. 复杂对象交互的系统
    • 在多个对象之间存在复杂交互的系统中,中介者模式非常适用。例如,GUI 控件交互(如按钮、文本框、下拉菜单等)可以通过中介者来管理。
  2. 消息队列系统
    • 在消息队列(如 JMS)中,中介者管理生产者和消费者之间的消息传递,解耦了消息的发送和接收,避免直接通信。
  3. 事件驱动系统
    • 在事件驱动架构中,事件发布者和监听者之间的通信可以通过中介者来协调,避免对象之间的紧密耦合。例如,Spring 的事件驱动机制利用 ApplicationEventPublisherApplicationListener 解耦了事件发布和处理。
  4. 航空管制系统
    • 像机场塔台这种需要协调多架飞机起降的系统,中介者可以集中管理对象的行为,保证复杂交互的有序进行。

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

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

相关文章

FedOV

3 FEDOV: ONE-SHOT FEDERATED OPEN-SET VOTING FRAMEWORK 3.1 PROBLEM STATEMENT 假设有个客户端及其本地数据集。我们的目标是在服务器的帮助下&#xff0c;在不交换原始数据的情况下&#xff0c;训练一个优秀的机器学习模型 。此外&#xff0c;每个客户端只允许与服务器进行…

掌握Python-uinput:打造你的输入设备控制大师

文章目录 掌握Python-uinput&#xff1a;打造你的输入设备控制大师背景&#xff1a;为何Python-uinput不可或缺&#xff1f;Python-uinput是什么&#xff1f;如何安装Python-uinput&#xff1f;简单库函数使用方法创建虚拟设备模拟按键模拟鼠标移动模拟滚轮滚动关闭设备 场景应…

ffmpeg 拉流

# 保存为视频 sudo ffmpeg -hwaccel rkmpp -vcodec h264_rkmpp -i "rtsp://user:passwdip:554" -c copy ./out.mp4 # 保存图片 ffmpeg -i "rtsp//" -y -f image2 -r 10/1 ../ffmpegData/img%03d.jpg jetson nano 查看解码器&#xff1a; ffmpeg -decode…

跟《经济学人》学英文:2024年09月21日这期 Britain should let university tuition fees rise

Britain should let university tuition fees rise Domestic students have been paying less in real terms every year 原文&#xff1a; In 2012 politicians in Britain burned lots of political capital by raising the cap on how much English universities can cha…

Type-C接口便携屏方案

随着科技的飞速发展&#xff0c;便携式电子产品在我们的日常生活中扮演着越来越重要的角色。在这一背景下&#xff0c;Type-C接口便携显示器作为一种新兴的显示设备&#xff0c;凭借其独特的优势迅速崭露头角&#xff0c;成为市场的新宠。本文将深入探讨Type-C接口便携显示器的…

vue无法通过页面路径访问提示404,通过nginx配置处理

部署vue项目时&#xff0c;可以通过IP的方式访问主页&#xff0c;当进入特定页面在刷新时&#xff0c;因为浏览器通过URL地址进行请求&#xff0c;就提示404错误。 每次都需要重新从主页进入&#xff0c;这里是因为nginx配置的问题&#xff0c;在nginx里增加一行重定向的设置 …

OJ 旋转图像

题目&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例&#xff1a; 解题规律: 我们以题目中的示例二作为例子&a…

一键快速替换PPT上的字体?这个你一定要学会。

前言 最近有个朋友在做PPT&#xff0c;说是准备在各大平台分发&#xff0c;咨询小白关于PPT上内容的事情&#xff0c;结果小白问了一句&#xff1a;字体用的是什么&#xff1f; 嗯……她说是&#xff1a;汉仪黑和字魂。 好家伙&#xff0c;这不是妥妥的当别人财神爷的机会吗&…

神奇的css动画:animation、transform、transition

前言 动画包括两个部分&#xff1a;描述动画的样式和用于指定动画开始、结束以及中间点样式的关键帧。 相比较于传统的脚本实现动画技术&#xff0c;使用css动画三个主要优点: 1.能够非常容易创建简单动画&#xff0c;甚至不需要了解JavaScript就能创建动画 2.动画运行效果…

进制转换,原码,反码,补码,二进制位运算及应用

进制转换 2B&#xff08;0--1)&#xff0c;8O(0--7)&#xff0c;10D&#xff0c;16H&#xff08;0——9,A——F&#xff09; 8位二进制数&#xff0c;左边高位&#xff0c;右边低位 2&#xff0c;8&#xff0c;16 -> 10进制整数&#xff0c;小数 整数&#xff1a;从后往…

iftop流量监控工具

一、iftop简介 iftop可以用来监控网卡的实时流量&#xff08;可以指定网段&#xff09;、反向解析IP、显示端口信息等&#xff0c;详细的将会在后面的使用参数中说明。 二、安装iftop 1、编译安装 如果采用编译安装可以到iftop官网下载最新的源码包。 1.1 CentOS上安装所需…

有没有自带财务管理功能的海外仓系统?

在全球化的商业环境中&#xff0c;海外仓作为连接国际市场的物流枢纽&#xff0c;其重要性日益凸显。然而&#xff0c;随着业务范围的扩展和费用类型的多样化&#xff0c;海外仓在财务管理上面临着诸多挑战。传统的手工计费和对账方式不仅耗时费力&#xff0c;而且容易出错&…

记录一次fs配置导致串线的问题

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 fs在实际的使用过程中也会经常碰到莫名其妙的问题&#xff0c;大部分都是配置问题。 环境 CentOS 7.9 freeswitch 1.10.7 docker 26.1.1 问题描述 组网方案如下。其中的fs-reg是注册服务器&#xff0c;fs1和fs2是…

栈的各种接口的实现(C)

栈的概念 栈&#xff1a; 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。压栈&#xff1a;…

join 命令:合并文件

一、命令简介 ​join​ 命令用于合并两个文件&#xff0c;基于一个共同的键&#xff08;key&#xff09;字段&#xff0c;将一个文件中的行与另一个文件中的行合并在一起。 这个键字段在两个文件中必须是相同的&#xff0c;这样 join 才能正确地将行匹配在一起。 ‍ 二、命…

linux系统维护:给linux的根目录分配更多的额外的磁盘空间,实现系统磁盘容量的平滑升级

目录 一、背景说明 二、概念介绍 1、物理卷&#xff08;Physical Volume, PV&#xff09; 2、卷组&#xff08;Volume Group, VG&#xff09; 3、逻辑卷&#xff08;Logical Volume, LV&#xff09;&#xff1a; 三、操作过程 1、vmware中新增磁盘 2、查看磁盘信息 3、格式化…

进阶版水仙花数水是指一个n位数,各个位数字的n次方之和等于该数字本身

两种方法&#xff1a; 第一种&#xff0c;是输入一个数值&#xff0c;判断是否为水仙花数 //打印水仙花数 //水仙花数是指一个n位数&#xff0c;各个位数字的n次方之和等于该数字本身 //如&#xff1a;1531^35^33^3 // //分析&#xff1a; //153/1015 //15/101 //1/100 #incl…

✨机器学习笔记(五)—— 神经网络,前向传播,TensorFlow

Course2-Week1: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Advanced%20Learning%20Algorithms/week1机器学习笔记&#xff08;五&#xff09; 1️⃣神经网络&#xff08;Neural Network&#xff09;2️⃣前向传播&#xff08;Forward propaga…

【C++】list容器的基本使用

一、list是什么 list的底层结构是带头双向循环链表。 相较于 vector 的连续线性空间&#xff0c;list 就显得复杂很多&#xff0c;它是由一个个结点构成&#xff0c;每个结点申请的空间并不是连续的&#xff0c;它的好处是每次插入或删除一个数据&#xff0c;就配置或释放一个…

MATLAB绘图基础8:双变量图形绘制

参考书&#xff1a;《 M A T L A B {\rm MATLAB} MATLAB与学术图表绘制》(关东升)。 8.双变量图形绘制 8.1 散点图 散点图用于显示两个变量间的关系&#xff0c;每个数据点在图上表示为一个点&#xff0c;一个变量在 X {\rm X} X轴&#xff0c;一个变量在 Y {\rm Y} Y轴&#…