设计模式- 中介者模式(Mediator)

1. 概念

  • 中介者模式(Mediator Pattern),是一种对象行为型模式。该模式的主要目的是定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合变得松散,并且可以独立地改变它们之间的交互。

2. 原理结构图

在这里插入图片描述

  • 抽象中介者(Mediator):这是中介者模式的核心接口,它定义了同事对象注册和信息转发的抽象方法。这个角色的主要职责是声明并规范中介者的操作,以便具体中介者能够实现这些操作来协调同事对象之间的交互。
  • 具体中介者(Concrete Mediator):这个角色实现了抽象中介者接口,并具体定义了一个管理同事对象的列表。它负责协调各个同事角色之间的交互关系,因此依赖于同事角色。
  • 抽象同事类(Colleague):这个角色定义了同事类的接口,它包含了保存中介者对象的方法和提供同事对象交互的抽象方法。这个角色的目的是实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague):这是抽象同事类的实现者。当具体同事类需要与其他同事对象交互时,它会通过中介者对象来进行后续的交互,而不是直接与其他同事对象通信。

3. 代码示例

3.1 示例1-聊天室系统
  • 在这个场景中,每个用户(客户端)都可以看作是一个同事类,而聊天室服务器则充当中介者的角色。用户之间不需要直接通信,而是通过服务器来转发消息。
import java.util.ArrayList;
import java.util.List;// 聊天室服务器,作为中介者
class ChatRoom {private List<User> users = new ArrayList<>();// 用户加入聊天室public void registerUser(User user) {users.add(user);user.setChatRoom(this);System.out.println(user.getName() + " has joined the chat room.");}// 用户离开聊天室public void unregisterUser(User user) {users.remove(user);System.out.println(user.getName() + " has left the chat room.");}// 发送消息给所有用户public void broadcast(User sender, String message) {for (User user : users) {if (!user.equals(sender)) {user.receive(sender.getName() + ": " + message);}}}
}// 用户(同事类)
class User {private String name;private ChatRoom chatRoom;public User(String name) {this.name = name;}public String getName() {return name;}public void setChatRoom(ChatRoom chatRoom) {this.chatRoom = chatRoom;}// 用户发送消息public void send(String message) {chatRoom.broadcast(this, message);}// 用户接收消息public void receive(String message) {System.out.println(this.name + " received: " + message);}
}// 聊天室客户端模拟
public class ChatRoomDemo {public static void main(String[] args) {ChatRoom chatRoom = new ChatRoom();User user1 = new User("Alice");User user2 = new User("Bob");User user3 = new User("Charlie");chatRoom.registerUser(user1);chatRoom.registerUser(user2);chatRoom.registerUser(user3);// Alice 发送消息user1.send("Hello everyone!");// Bob 发送消息user2.send("Hi Alice, how are you?");// Charlie 离开聊天室chatRoom.unregisterUser(user3);// Alice 再次发送消息,Charlie 不再接收user1.send("Charlie, are you there?");}
}
  • 将看到如下输出:
Alice has joined the chat room.
Bob has joined the chat room.
Charlie has joined the chat room.
Bob received: Alice: Hello everyone!
Charlie received: Alice: Hello everyone!
Alice received: Bob: Hi Alice, how are you?
Charlie received: Bob: Hi Alice, how are you?
Charlie has left the chat room.
Bob received: Alice: Charlie, are you there?
  • 在这个例子中,ChatRoom 类充当了中介者的角色,它维护了一个用户列表,并提供了注册用户、注销用户以及广播消息的方法。User 类代表了聊天室中的用户,每个用户都有一个名字,并且可以发送和接收消息。用户通过调用 send 方法来发送消息,而消息则通过 ChatRoom 的 broadcast 方法广播给所有其他用户。
  • 在 main 方法中,我们创建了一个 ChatRoom 实例和三个 User 实例,并模拟了用户加入聊天室、发送消息以及离开聊天室的过程。
  • 这个简单的例子展示了中介者模式在聊天室系统中的应用,通过中介者(聊天室服务器)来管理用户之间的通信,降低了用户之间的耦合度,使得系统更加灵活和易于维护。在实际应用中,聊天室系统会更加复杂,可能需要处理更多的功能,如用户身份验证、消息历史记录、私有聊天等,但中介者模式的基本思想仍然适用。

3.2 示例2-智能家居系统
  • 在智能家居系统中,中介者模式可以应用于管理各种智能设备之间的交互。这些设备可能包括灯光、空调、电视、窗帘等,每个设备都作为同事类,而智能家居中心或服务器则作为中介者,负责协调和管理设备之间的通信和交互。
import java.util.HashMap;
import java.util.Map;// 智能家居系统的中介者,负责管理设备间的交互
class SmartHomeCenter {private Map<String, SmartDevice> devices = new HashMap<>();// 注册设备public void registerDevice(SmartDevice device) {devices.put(device.getName(), device);device.setSmartHomeCenter(this);}// 注销设备public void unregisterDevice(SmartDevice device) {devices.remove(device.getName());}// 接收设备发送的命令并转发给相关设备public void receiveCommand(SmartDevice sender, String command, String target) {SmartDevice targetDevice = devices.get(target);if (targetDevice != null && !targetDevice.equals(sender)) {targetDevice.receiveCommand(sender, command);} else {System.out.println("Target device not found or is the sender itself.");}}
}// 智能设备接口
interface SmartDevice {String getName();void setSmartHomeCenter(SmartHomeCenter center);void sendCommand(String command, String target);void receiveCommand(SmartDevice sender, String command);
}// 具体的智能设备类,如灯光
class Light implements SmartDevice {private String name;private SmartHomeCenter center;public Light(String name) {this.name = name;}@Overridepublic String getName() {return name;}@Overridepublic void setSmartHomeCenter(SmartHomeCenter center) {this.center = center;}@Overridepublic void sendCommand(String command, String target) {center.receiveCommand(this, command, target);}@Overridepublic void receiveCommand(SmartDevice sender, String command) {System.out.println(name + " received command from " + sender.getName() + ": " + command);// 执行相应的命令逻辑,如开关灯等}
}// 假设的空调类,实现SmartDevice接口
class AirConditioner implements SmartDevice {private String name;private SmartHomeCenter center;public AirConditioner(String name) {this.name = name;}@Overridepublic String getName() {return name;}@Overridepublic void setSmartHomeCenter(SmartHomeCenter center) {this.center = center;}@Overridepublic void sendCommand(String command, String target) {center.receiveCommand(this, command, target);}@Overridepublic void receiveCommand(SmartDevice sender, String command) {System.out.println(name + " received command from " + sender.getName() + ": " + command);// 执行相应的命令逻辑,如开关空调、调节温度等}
}// 智能家居系统客户端模拟
public class SmartHomeDemo {public static void main(String[] args) {SmartHomeCenter center = new SmartHomeCenter();SmartDevice light1 = new Light("Living Room Light");SmartDevice ac1 = new AirConditioner("Living Room AC");center.registerDevice(light1);center.registerDevice(ac1);// 客厅灯光发送命令给空调,要求其关闭light1.sendCommand("turnOff", ac1.getName());// 注销设备center.unregisterDevice(light1);// 再次尝试发送命令,由于灯光已注销,将不会执行light1.sendCommand("turnOn", ac1.getName());}
}
  • 将看到如下输出:
Living Room AC received command from Living Room Light: turnOff
Living Room AC received command from Living Room Light: turnOn
  • SmartHomeDemo 类中,我们模拟了智能家居系统的客户端行为。首先,我们创建了 SmartHomeCenter 实例和两种智能设备实例 Light 和 AirConditioner,并将它们注册到中介者中。接着,我们通过调用 Light 实例的 sendCommand 方法来模拟发送命令给 AirConditioner 实例,要求其关闭。因为中介者负责协调设备间的通信,所以命令通过中介者正确地发送到了 AirConditioner。
  • 最后,我们注销了 Light 实例,并尝试再次发送命令。由于该设备已被注销,中介者不会将命令转发给 AirConditioner,从而模拟了设备离线或未注册的情况。
  • 这只是一个非常简单的示例,真实的智能家居系统会更复杂,涉及更多的设备类型、通信协议、安全机制以及用户界面交互等。但通过这个例子,你应该能够理解中介者模式在智能家居系统中如何工作,以及它是如何简化设备间通信和交互的。
  • 在实际应用中,你还需要考虑设备之间的异步通信、错误处理、设备状态管理以及与其他系统的集成(如语音助手、移动应用等)。此外,对于大规模部署和复杂的家居环境,可能需要更高级的架构设计和性能优化。

4. 优缺点

  • 主要作用
    • 降低对象之间的耦合性,并简化它们之间的通信。
  • 优点
    • 实现解耦合:各个对象不再直接相互依赖,而只依赖于中介者,这显著降低了类之间的耦合性。
    • 简化交互:中介者模式简化了对象之间的交互过程。在复杂的系统中,对象之间可能存在大量的交互关系,如果直接进行通信,将导致代码复杂且难以维护。通过中介者进行集中管理,可以将复杂的交互逻辑封装在中介者内部,简化了对象之间的通信过程,使得代码更加清晰和易于理解。
    • 可扩展性:中介者模式使得系统更加易于扩展。当需要添加新的对象或新的交互关系时,只需要修改中介者的代码,而无需修改其他对象的代码。这降低了系统的扩展难度,提高了系统的可扩展性。
    • 统一控制:中介者模式实现了对交互关系的统一控制。通过中介者,可以对对象之间的交互进行全局的管理和协调,确保交互的正确性和一致性。这有助于避免由于对象之间的直接通信而导致的混乱和错误。
  • 缺点
    • 中介者可能变得过于复杂:随着系统中同事类数量的增加,中介者需要管理的交互关系也会变得更为复杂。这可能导致中介者类的逻辑变得庞大且难以维护,增加了系统的复杂性。
    • 可能导致系统性能下降:由于所有对象间的交互都需要通过中介者进行,当交互频繁或涉及大量数据时,中介者可能成为性能瓶颈,导致系统响应速度变慢。
    • 降低了系统的透明度:由于交互逻辑被封装在中介者内部,外部对象无法直接了解其他对象的交互细节。这降低了系统的透明度,使得理解和调试系统变得更加困难。
    • 对中介者的依赖性强:同事类依赖于中介者进行交互,如果中介者出现问题或无法正常工作,整个系统可能会受到影响。这增加了系统的风险,需要确保中介者的稳定性和可靠性。

5. 应用场景

5.1 主要包括以下几个方面
  1. 对象关系复杂:当系统中的对象之间存在复杂的引用关系,导致结构混乱难以理解时,引入中介者可以简化这些关系。
  2. 行为变更频繁:如果系统需要频繁地改变对象间的交互行为,可以通过增加新的中介者类来实现,这样有助于保持系统的灵活性。
  3. 多人交互场景:例如多人聊天室,一个人发言需要传达给每个人,如果没有聊天室(中介者),则需要对每个人都说一遍;有了中介者,就由它负责传达,减少了个体之间的直接交互。
  4. 系统解耦要求高:在需要降低对象间直接依赖,提高系统模块独立性的情况下,中介者模式是一个很好的选择。
  5. 复杂系统设计:对于复杂的系统如GUI系统、企业应用程序等,使用中介者模式可以使系统更易于维护和扩展。

5.2 实际应用
  1. 聊天室系统:在一个聊天室应用中,用户之间的消息传递不需要直接相互引用。通过中介者,即聊天室服务器,来协调消息的发送和接收,这样每个用户只需与服务器交互即可。
  2. 微服务架构:在微服务架构中,不同的服务之间通过一个中介者来进行通信,这个中介者通常是服务总线或者消息队列,它负责传递和路由消息,降低了服务间的直接依赖。
  3. 智能家居系统:在智能家居系统中,各种设备如灯光、温度控制器、安全摄像头等,可以通过一个中心控制系统来协调它们的工作,而不是直接相互通信。
  4. 多人游戏:在多人在线游戏中,玩家之间的互动(如聊天、交易、组队等)可以通过一个游戏服务器来中介,这样可以避免玩家之间直接建立连接,减少了系统的复杂性。

6. JDK中的使用

  • java.util.Timer 类
    • 中介者角色(Timer)
      • Timer类提供了注册任务(通过schedule方法)和取消任务的方法,这些方法允许同事类(即需要定时执行的任务)与中介者进行交互。
      • Timer内部维护了一个任务队列,并负责按照指定的时间间隔或延迟来执行这些任务。它协调了各个任务之间的执行顺序和时间,确保它们能够按照预期的方式运行。
    • 同事类角色(TimerTask 或其他实现 Runnable 接口的类)
      • 这些类表示需要定时执行的任务,它们实现了Runnable接口或继承了TimerTask类,并定义了任务的具体执行逻辑。
      • 同事类通过调用Timer类的schedule方法将自己注册到中介者中,并指定执行的时间和周期。一旦注册成功,它们就不再需要直接与其他任务进行交互,而是依赖于Timer中介者来管理和调度它们的执行。

7. 注意事项

  • 避免过度集中控制:虽然中介者有助于降低系统的耦合度,但过度依赖中介者可能导致中介者类的职责过重,增加维护难度。
  • 保持中介者的简洁性:中介者应专注于协调和转发消息,避免在其中引入过多的业务逻辑。
  • 适时重构:随着系统的发展,中介者可能会变得复杂,需要定期审视并重构以保持系统的清晰和可维护性。
  • 性能考量:在某些高性能需求的场景中,中介者可能成为性能瓶颈,需注意性能优化。
  • 扩展性设计:设计时应考虑未来可能的变化,确保中介者模式的实现能够适应新的需求和变化。

8. 中介者模式 VS 组合模式

模式类型目的模式架构主要角色应用场景
中介者模式行为型简化对象间复杂交互,降低耦合度中介者、同事类对象间交互复杂且需要解耦时
组合模式结构型统一处理组合对象与单个对象,表达层次结构组合对象、叶子对象需要表示部分-整体层次结构时

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

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

相关文章

Python Selenium无法打开Chrome浏览器处理自定义浏览器路径

问题 在使用Python Selenium控制Chrome浏览器操作的过程中&#xff0c;由于安装的Chrome浏览器的版本找不到对应版本的驱动chromedriver.exe文件&#xff0c;下载了小几个版本号的驱动软件。发现运行下面的代码是无法正常使用的&#xff1a; from selenium import webdriver …

FPGA“题目周周练”活动来啦!

Hi&#xff0c;各位编程精英er~ 不知道大家的FPGA学习之旅到达哪一个阶段了呢&#xff1f;又在这个过程中遇到了哪些困惑&#xff1f; 作为一门高度专业化且充满挑战的技术&#xff0c;FPGA的学习是一场不断思考、认知、持续深化的过程。在这个过程中&#xff0c;思维的敏捷和…

【vue2】实现微信截图(复制图片)在项目内可粘贴

需求 后台管理在上传图片地方需要将复制的图片粘贴上传 一、添加事件 在原有上传组件的基础上添加 paste事件 二、方法 onPaste(e) {const items (e.clipboardData || window.clipboardData).items;let blob null;for (let i 0; i < items.length; i) {if (items[i].ty…

034——从GUI->Client->Server->driver实现读写EEPROM

目录 1、修改GUI 2、修改client 3、 修改server 4、 修改driver_handele 5、 测试和提交 1、修改GUI 之前叫IIC&#xff0c;我们其实是借助EEPROM来测试IIC是不是好用所以名称改一改 长得有点奇怪 这样虽然一样长了但是还是很奇怪。 就先这样吧 layout_l [[tool.name(N…

100个实用电气知识

在当今社会&#xff0c;电力作为日常生活和工作中不可或缺的能源&#xff0c;扮演着越来越重要的角色。为了更好地利用电力资源&#xff0c;了解电气知识成为了越来越多人的需求。在电气领域&#xff0c;有很多实用的知识&#xff0c;这些知识对于从事电气工作的人来说是非常重…

二叉树oj题(2)

1.二叉树的最近公共祖先 解题思路&#xff1a;方法一&#xff1a; 1.先判断p或者q 是不是 root当中的一个 2.左子树当中递归査找p或者q 3.右子树当中递归查找p或者q 如何查找: root 的 left 和 right 都不为空 ->root root的 left 为空 right 不为空->right这一侧找…

出海不出局 | 小游戏引爆高线市场,新竞争态势下的应用出海攻略

出海小游戏&#xff0c;出息了&#xff01; 根据 Sensor Tower 近期发布的“2024 年 3 月中国手游收入 TOP30”榜单&#xff0c;出海小游戏在榜单中成了亮眼的存在。 其中&#xff0c;《菇勇者传说》3 月海外收入环比增长 63%&#xff0c;斩获出海手游收入增长冠军&#xff0c…

vue element-ui 表格横向滚动条在合计项下方

目前效果 需求效果 1.隐藏bodyWrapper滚动条&#xff0c;显示footerWrapper滚动条 css代码如下&#xff1a; div ::v-deep .el-table--scrollable-x .el-table__body-wrapper{overflow-x: hidden!important;z-index: 2!important;} div ::v-deep .el-table__footer-wrapper …

理发师问题的业务建模方案

背景 题目&#xff1a; 假设有一个理发店只有一个理发师&#xff0c;一张理发时坐的椅子&#xff0c;若干张普通椅子顾客供等候时坐。没有顾客时&#xff0c;理发师睡觉。顾客一到&#xff0c;叫醒理发师 。如果理发师没有睡觉&#xff0c;而在为别人理发&#xff0c;他就会坐…

Android—— log的记忆

一、关键log 1.Java的 backtrace(堆栈log) 上述是一个空指针异常&#xff0c;问题出现在sgtc.settings&#xff0c;所以属于客户UI问题。 2.WindowManager(管理屏幕上的窗口和视图层次结构) 3.ActivityManager(管理应用程序生命周期和任务栈) 4.wifi操作 (1) 连接wifi&#…

开源大模型Llama3,堪比GPT-4。手把手本地安装,纯小白可操作,不需要编程经验,国内可下载,可视化使用。

最近最劲爆科技动态&#xff0c;Meta开源Llama3模型&#xff0c;最强开源模型。 Llama3发布后&#xff0c;扎克伯格亲自给媒体表示“要超越所有人&#xff0c;做最领先AI”。 吴恩达等一众大佬表示祝贺。 在线体验地址&#xff1a;https://www.meta.ai/ 不过国内在线体验基本…

OpenWRT磁盘扩容(PVE虚拟机方案)

官方扩容指导文档 PVE给虚拟机磁盘扩容 给虚拟机磁盘扩容&#xff0c;选中OpenWRT的硬盘&#xff0c;随后选择调整大小 输入增量大小&#xff0c;即增加多少磁盘空间给硬盘。这里我选择增加4G 进入OpenWRT控制台界面安装一些linux常用查看磁盘的工具&#xff08;也可以通过网…

EasyPoi实现简单的Excel导出、导入

EasyPoi实现Excel导出、导入 下面这种方式不需要模板&#xff0c;更加方便但是不能进行复杂的导出 一、引入依赖 <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.4.0</version><…

2024商业地产五一劳动节健康大会朋克养生市集活动策划方案

2024商业地产五一劳动节健康大会朋克养生市集&#xff08;带薪健康 快乐打工主题&#xff09;活动策划方案 活动策划信息&#xff1a; 方案页码&#xff1a;53页 文件格式&#xff1a;PPT 方案简介&#xff1a; 打工不养生 赚钱养医生 期待已久的五一假期&#xff0c; …

mysql download 2024

好久没在官网下载 mysql server 安装包。今天想下载发现&#xff1a; 我访问mysql官网的速度好慢啊。mysql server 的下载页面在哪里啊&#xff0c;一下两下找不到。 最后&#xff0c;慢慢悠悠终于找到了下载页面&#xff0c;如下&#xff1a; https://dev.mysql.com/downlo…

什么是全局特征,什么又是局部特征

全局特征和局部特征是用来描述数据中信息的两种不同方式&#xff0c;特别是在图像处理、模式识别和机器学习领域中经常被提到。它们有助于理解和分析数据的不同层面&#xff1a; 全局特征&#xff08;Global Features&#xff09; 全局特征描述了整个数据集的整体属性。在图像…

windows和linux服务器等保测评加固方法

服务器加固是通过各种方法增强服务器安全性的过程。保护操作系统免受黑客、破解者和攻击者的侵害。网络安全防护的目标是保密性、完整性、可用性、可控制性、不可否认性。 一、window服务器等保加固 以win2012和win2008 为例&#xff1a; &#xff08;win2008&#xff09; …

【UML建模】用例图

1 参与者 参与者的概念&#xff1a; 指系统以外的、需要使用系统或与系统交互的外部实体 可以分为&#xff1a;人、外部设备、外部系统 参与者的图形符号&#xff1a; 例 3.1 在一个银行业务系统中&#xff0c;可能会有以下参与者 客户 &#xff1a;在银行业务系统中办理…

React【Day2】

React表单控制 受控绑定 概念&#xff1a;使用React组件的状态&#xff08;useState&#xff09;控制表单的状态 双向绑定 MVVM 报错记录&#xff1a; 错误代码&#xff1a; import { useState } from "react";const App () > {const [value, setValue] useS…

TLV61048非同步升压BOOST转换器输入电压2.6-5.5V输出电流4A输出电压最高15V

推荐原因&#xff1a; 输入电压较低&#xff0c;输出电流可达3.5A SOT23-6封装 批量价格约0.70元 TLV61048引脚 TLV61048引脚功能 7 详细说明 7.1 概述 TLV61048是一款非同步升压转换器&#xff0c;支持高达 15 V 的输出电压和输入范围从 2.61 V 到 5.5 V。该TLV61048集成了…