中介模式简介

news/2024/10/18 16:55:27/

概念

中介者模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介者对象来解耦多个相关对象之间的交互。中介者充当了多个对象之间的协调者,使得这些对象不需要直接相互通信,而是通过与中介者进行通信。中介者模式用于将一组相关对象的复杂交互逻辑封装到一个单独的类(即中介者)中。该类负责协调和管理这些对象之间的通信,并提供统一的接口供其他对象使用。

特点

  1. 解耦关联对象:通过引入一个中介者来减少各个相关对象之间的直接依赖关系。
  2. 集中控制逻辑:将复杂的交互逻辑集中在一个类(即中介者)中管理和处理。
  3. 促进可扩展性:新添加或修改现有相关对象时,只需修改或扩展具体实现类而无需改变其他部分。

优点

  1. 减少了多对多关系:将原本复杂且混乱的多对多关系转化为简单明确、清晰易懂且易维护的一对多关系。
  2. 提高了系统灵活性:由于各个同事类只依赖于抽象 Mediator 类,因此可以在不修改同事类的情况下增加新的中介者。
  3. 降低了对象之间的耦合性:各个同事类只需要知道中介者对象,而无需了解其他同事类的具体细节。

缺点

  1. 中介者模式会导致中介者本身变得复杂,因为它需要处理多个相关对象之间的交互逻辑。
  2. 当系统中出现太多相关对象时,可能会导致中介者过于庞大和复杂。

适用场景

  1. 系统内部各个对象之间存在复杂且紧密耦合的关系。
  2. 一个行为会影响其他相关对象,并且希望减少这些相互依赖关系。
  3. 需要集中控制一组相关对象之间的交互逻辑。

实现方式

基于接口实现

实现原理:

定义一个抽象 Mediator 接口来约束具体 Mediator 类,并在其中声明各种协调方法。然后创建具体 Mediator 类来实现该接口,并在其中管理和协调相关对象之间的通信与交互逻辑。

实现代码:

mport java.util.ArrayList;
import java.util.List;// 中介者接口
interface Mediator {void sendMessage(String message, Colleague colleague);void addColleague(Colleague colleague);
}// 具体中介者类
class ConcreteMediator implements Mediator {private List<Colleague> colleagues;public ConcreteMediator() {this.colleagues = new ArrayList<>();}public void addColleague(Colleague colleague) {colleagues.add(colleague);}@Overridepublic void sendMessage(String message, Colleague colleague) {// 将消息广播给其他同事对象(除了发送方自身)for (Colleague c : colleagues) {if (c != colleague) {c.receiveMessage(message);}}}
}// 同事类接口
interface Colleague {void receiveMessage(String message);void sendMessage(String message);
}// 具体同事类A
class ConcreteColleagueA implements Colleague {private Mediator mediator;public ConcreteColleagueA(Mediator mediator){this.mediator=mediator;mediator.addColleague(this);}@Overridepublic void receiveMessage(String message) {System.out.println("ConcreteColleage A received: " + message);}@Overridepublic void sendMessage(String message) {System.out.println("ConcreteColleage A sent: " +message );mediator.sendMessage(message, this);}
}// 具体同事类B
class ConcreteColleagueB implements Colleague {private Mediator mediator;public ConcreteColleagueB(Mediator mediator){this.mediator=mediator;mediator.addColleague(this);}@Overridepublic void receiveMessage(String message) {System.out.println("ConcreteColleage B received: " +message );}@Overridepublic void sendMessage(String message) {System.out.println("ConcreteColleage B sent: " + message);mediator.sendMessage(message, this);}
}public class Main {public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();Colleague colleagueA = new ConcreteColleagueA(mediator);Colleague colleagueB = new ConcreteColleagueB(mediator);colleagueA.sendMessage("Hello, how are you?");colleagueB.sendMessage("I'm fine, thank you!");}
}

在上述示例中,我们定义了一个中介者接口 Mediator 和具体实现类 ConcreteMediator。然后创建了两个同事类 ConcreteColleague A ConcreteColleague B,并在其构造函数中将中介者对象传递进去。当同事对象需要发送消息时,会通过中介者进行广播并通知其他相关对象。

基于事件机制

基于事件机制的中介者模式是指通过使用观察者模式作为基础,将中介者类作为发布器(Publisher),其他相关对象作为订阅器(Subscriber)来实现。当某个对象发生变化时,通过中介者发布对应的事件通知其他相关对象进行相应操作。

实现原理:

  1. 定义一个抽象的中介者接口,其中包含注册、解注册和广播事件等方法。
  2. 创建具体的中介者类并实现抽象接口,在其中维护一个订阅器列表,并实现注册、解注册和广播事件等方法。
  3. 定义订阅器接口,其中包含处理事件的方法。
  4. 创建多个具体订阅器类并实现订阅器接口,在其中定义处理不同类型事件的具体逻辑。
  5. 当某个对象需要发送消息时,调用中介者的广播事件方法,在该方法内部遍历所有订阅器,并根据不同类型调用对应订阅器的处理方法。

实现代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;// 中介者接口
interface Mediator {void register(String eventType, Subscriber subscriber);void unregister(String eventType, Subscriber subscriber);void broadcastEvent(String eventType, Object data);
}// 具体中介者类
class ConcreteMediator implements Mediator {private Map<String, List<Subscriber>> subscribers;public ConcreteMediator() {this.subscribers = new HashMap<>();}@Overridepublic void register(String eventType, Subscriber subscriber) {if (!subscribers.containsKey(eventType)) {subscribers.put(eventType, new ArrayList<>());}subscribers.get(eventType).add(subscriber);}@Overridepublic void unregister(String eventType, Subscriber subscriber) {if (subscribers.containsKey(eventType)) {subscribers.get(eventType).remove(subscriber);if (subscribers.get(eventType).isEmpty()) { // 如果没有订阅者,移除该事件类型的列表subscribers.remove(eventType);}}}@Overridepublic void broadcastEvent(String eventType, Object data) {if (subscribers.containsKey(eventType)) {for (Subscriber s : subscribers.get(eventType)) {s.handleEvent(data);}}}}// 订阅器接口
interface Subscriber {void handleEvent(Object data);}// 具体订阅器类A
class ConcreteSubscriberA implements Subscriber{@Overridepublic void handleEvent(Object data){System.out.println("ConcreteSubscriber A received: " +data );}}// 具体订阅器类B
class ConcreteSubscriberB implements Subscriber{@Overridepublic void handleEvent(Object data){System.out.println("ConcreteSubscriberB received: " +data );}
}public class Main {public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();Subscriber subscriberA = new ConcreteSubscriberA();Subscriber subscriberB = new ConcreteSubscriberB();mediator.register("event1", subscriberA);mediator.register("event2", subscriberB);// 发送事件通知mediator.broadcastEvent("event1", "Hello, how are you?");mediator.broadcastEvent("event2", "I'm fine, thank you!");// 解注册订阅器mediator.unregister("event1", subscriberA);// 再次发送事件通知,只有subscriberB会接收到mediator.broadcastEvent("event1","This message won't be received by any subscribers");mediator.broadcastEvent("event2","This message will be received by only one subscriber");}
}

在上述示例中,我们定义了一个中介者接口 Mediator 和具体实现类 ConcreteMediator。然后创建了两个订阅器类 ConcreteSubscribere A ConcreteSubscribere B,并在其中分别实现处理不同类型事件的具体逻辑。当需要发送消息时,调用中介者的广播事件方法,在该方法内部遍历所有订阅器,并根据不同类型调用对应订阅器的处理方法。


http://www.ppmy.cn/news/1103746.html

相关文章

Qt学习记录___9.10

1.QtSvg初体验 #include <QtSvg> QSvgWidget w1;w1.load(QString(":/iconfont-gongyichongwu.svg"));QSvgRenderer *renderw1.renderer();qDebug()<<render->defaultSize();w1.resize(render->defaultSize());w1.show(); 2. 对话框实验。 QT之隐藏…

YOLO的基本原理详解

YOLO介绍 YOLO是一种新的目标检测方法。以前的目标检测方法通过重新利用分类器来执行检测。与先前的方案不同&#xff0c;将目标检测看作回归问题从空间上定位边界框&#xff08;bounding box&#xff09;并预测该框的类别概率。使用单个神经网络&#xff0c;在一次评估中直接…

PLC-Recorder离线分析软件Ana里为什么不能显示变量的编号?

在PLC-Recorder在线软件里&#xff0c;大家可以在曲线上找到变量的编号&#xff08;由通道编号、变量类型、同类型序号组成&#xff09;。这个编号也是各软件识别变量的唯一标识。在变量和PLC很多时&#xff0c;可以方便地找到对应的PLC&#xff0c;如下&#xff1a; 有朋友问&…

30 | 工欲善其事必先利其器:后端性能测试工具原理与行业常用工具简介

对性能测试的理解和认识&#xff1a; 后端性能测试和后端性能测试工具之间的关系是什么&#xff1f; 后端性能测试工具和 GUI 自动化测试工具最大的区别是什么&#xff1f; 后端性能测试工具的原理是什么&#xff1f; 后端性能测试中&#xff0c;性能测试…

软件测试———linux

文章目录 基础1. 发展史2 特征3 内核版本号的特征4.发布版5,安装 第二章Linux的常见命令Linux命令vi的使用文件的操作文件的压缩和解压缩文件阅读命令权限的操作用户设置配置系统查看名命令 基础 1. 发展史 unix—>BSD(TCP的使用)---->GNU---->Minix—>linux 2 …

【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦

beanfactory 1.applicationcontext的父接口 2.是Spring的核心容器 功能 表面只有getBean&#xff0c;但实现类默默发挥了巨大作用 1.管理所有bean 2.控制反转 3.基本的依赖注入 applicationcontext 功能 1.继承了MessageSource&#xff0c;有了处理国际化资源的能力 …

2023Web前端开发面试手册

​​​​​​​​ HTML基础 1. HTML 文件中的 DOCTYPE 是什么作用&#xff1f; HTML超文本标记语言: 是一个标记语言, 就有对应的语法标准 DOCTYPE 即 Document Type&#xff0c;网页文件的文档类型标准。 主要作用是告诉浏览器的解析器要使用哪种 HTML规范 或 XHTML规范…

引入Bootstrap的CSS样式后,<h>标签、<p>标签等HTML自带的标签被覆写没有?答:覆写了。

引入Bootstrap的CSS样式后,标签、 标签等HTML自带的标签被覆写没有&#xff1f;答&#xff1a;覆写了。 为什么这么说&#xff1f;证据呢&#xff1f; 写一个实例&#xff0c;然后调试模式看一下不就得了。 先看没有引入引入Bootstrap的CSS样式情况。 代码如下&#xff1a; …