设计模式之中介者模式

阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. 本篇文章大概5000多字,预计阅读时间长需要5分钟。
  2. 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
  3. 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。

什么是中介者模式

        中介者模式是一种软件设计模式,它允许定义一个中间对象(中介者),来协调一组对象之间的交互。通过将一组对象之间的交互抽象化到一个单独的对象中,使得各个对象不必直接交互,而只与中介者发生交互,从而使原本复杂的多对多的关系变成相对简单的单对单或一对多的关系。

中介者模式有哪些核心角色

        中介者模式(Mediator Pattern)包含以下四个核心角色:

  1. Mediator(抽象中介者):用来定义参与者与中介者之间的交互方式,如同事角色的注册、注销、消息的转发。
  2. ConcreteMediator(具体中介者):实现抽象中介者接口,实现具体交互方式。
  3. Colleague(抽象同事角色):抽象类或者接口,定义参与者如何进行交互,如发送消息、接收消息等。
  4. ConcreteColleague(具体同事角色):实现Colleague中的方法,定义具体行为。

        中介者模式的目的是通过引入中介者来简化对象之间的复杂交互,将多对多的复杂关系转化为相对简单的一对多关系。中介者的职责是进行结构性中转作用和协调行为。结构性中转作用是指各个同事对象不再需要显式地引用其他同事,当需要和其他同事进行通信时,可通过中介者来实现间接调用。协调行为是指中介者可以更进一步地对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑对同事的请求进行进一步处理。

// 抽象中介者  
public abstract class Mediator {public abstract void register(Colleague colleague);public abstract void relay(Colleague cl); //转发
}
public class ConcreteMediator extends Mediator {private List<Colleague> colleagues = new ArrayList<Colleague>();public void register(Colleague colleague) {if (!colleagues.contains(colleague)) {colleagues.add(colleague);colleague.setMedium(this);}}public void relay(Colleague cl) {for (Colleague ob : colleagues) {if (!ob.equals(cl)) {((Colleague) ob).receive();}}}
}
//抽象同事类
public abstract class Colleague {protected Mediator mediator;public void setMedium(Mediator mediator) {this.mediator = mediator;}public abstract void receive();public abstract void send();
}
//具体同事类
public class ConcreteColleague1 extends Colleague {public void receive() {System.out.println("具体同事类1收到请求。");}public void send() {System.out.println("具体同事类1发出请求。");mediator.relay(this); //请中介者转发}
}
//具体同事类
class ConcreteColleague2 extends Colleague {public void receive() {System.out.println("具体同事类2收到请求。");}public void send() {System.out.println("具体同事类2发出请求。");mediator.relay(this); //请中介者转发}
}
public class MediatorPattern {public static void main(String[] args) {Mediator md = new ConcreteMediator();Colleague c1, c2;c1 = new ConcreteColleague1();c2 = new ConcreteColleague2();md.register(c1);md.register(c2);c1.send();System.out.println("-------------");c2.send();}
}

中介者模式如何实现

需求描述

        通过上面的介绍,相信对中介者模式已经有了一个大概的印象了,这里再模拟一个业务场景来重点理解一下,中介者模式中各角色之间是如何交互的.

        以前在农村的村部都会有一个大喇叭,上级有什么通知啥的、或者是谁家有个啥喜事都是通过个大喇叭通知给全体村民的,这里的大喇叭实际上就相当于一个中介者的角色,村长可以用来通知上级的重要指示,其他村民也可用来通知自己的喜事.如果使用中介者模式写一段程序来模拟这个过程,应该怎么实现呢?

实现方法

1、声明一个抽象的喇叭接口,即抽象中介者角色,定义两个抽象方法:注册喇叭的使用者、播放消息;

/*** 抽象喇叭*/
public interface Horn {/*** 注册使用者* @param villager*/void register(Villager villager);/*** 播放消息* @param msg*/void play(Villager villager,String msg);
}

2、声明一个具体的喇叭类,即具体的中介者角色,实现抽象喇叭接口,实现其中定义的抽象方法;

/*** 具体的喇叭*/
public class ConcreteHorn implements Horn{private List<Villager> list=new ArrayList<>();@Overridepublic void register(Villager villager) {list.add(villager);villager.setHorn(this);}@Overridepublic void play(Villager villager,String msg) {for (Villager obj : list) {if (!obj.equals(villager)) {obj.receive(msg);}}}
}

3、声明一个抽象的村民类,即抽象同事类,每一个村民都有权利使用喇叭,因此在抽象村民类内部定义一个喇叭属性,另外定义两个抽象方法:用于接受其他村民发的消息和自己向其他村民发消息;

/*** 抽象村民*/
public abstract class Villager {protected Horn horn;public void setHorn(Horn horn) {this.horn = horn;}/*** 发消息* @param msg*/public abstract void send(String msg);/*** 收到消息* @param msg*/public abstract void receive(String msg);
}

4、声明具体的村民类,即具体的同事类,这里声明两个作为村民代表,一个是村长类,另一个是村民代表张三类,继承抽象的村民类,并实现抽象村民类中的两个抽象方法;

/*** 村长*/
public class VillageHead extends Villager{@Overridepublic void send(String msg) {this.horn.play(this,msg);}@Overridepublic void receive(String msg) {System.out.println("村长收到消息:"+msg);}
}
/*** 张三*/
public class ZhangSan extends Villager{@Overridepublic void send(String msg) {this.horn.play(this,msg);}@Overridepublic void receive(String msg) {System.out.println("张三收到消息:"+msg);}
}
/*** 其他村民*/
public class OtherVillager extends Villager{@Overridepublic void send(String msg) {this.horn.play(this,msg);}@Overridepublic void receive(String msg) {System.out.println("其他村民收到消息:"+msg);}
}

5、编写客户端业务,模拟村长给村民发送上级通知、和张三给其他村民发布喜讯通知;

public class Client {public static void main(String[] args) {Horn horn=new ConcreteHorn();Villager zhangsan=new ZhangSan();Villager otherVillager=new OtherVillager();Villager villageHead=new VillageHead();horn.register(zhangsan);horn.register(otherVillager);horn.register(villageHead);zhangsan.send("大家好,俺是村东头张三!俺娃考上县城第一中学了,晚上都到我家喝酒!");System.out.println("-------------");villageHead.send("各位村民注意了!上级调配的种子化肥已到村部,各家速来领取!");}
}

如何扩展

        生活水平提高了,村里喇叭年久失修,也不太好用了,于是村民一致支持在村头广场上建个LED大屏,用途和以前的喇叭一样,也是用来方便传递消息,晚上还插放个新闻联播。怎么实现呢?很简单重新定义LED类,实现抽象喇叭接口,然后再调整一个客户端业务就可以了;这样村里就有两套传递消息的机制了,互不影响;

public class LED implements Horn{private List<Villager> list=new ArrayList<>();@Overridepublic void register(Villager villager) {this.list.add(villager);villager.setHorn(this);}@Overridepublic void play(Villager villager, String msg) {for (Villager obj : list) {if (!obj.equals(villager)) {obj.receive(msg);}}}
}
public class Client {public static void main(String[] args) {Villager zhangsan=new ZhangSan();Villager otherVillager=new OtherVillager();Villager villageHead=new VillageHead();Horn horn=new LED();horn.register(zhangsan);horn.register(otherVillager);horn.register(villageHead);villageHead.send("村民们注意了!村里新修的大屏今天正式投入使用了,晚上放电影,铁道游击队!");}
}

        那么如果村里有新村民迁入了,应该怎么扩展,是不是也很简单了?

中介者模式适用哪些场景

        中介者模式适用于具有以下特征的业务场景:

  • 多个对象之间存在着复杂的关联和交互关系,使得系统难以理解和维护;
  • 需要通过一个中间对象来封装多个对象之间的交互,以提高代码的可读性和可维护性;
  • 在系统中需要频繁地添加、删除或改变对象之间的交互关系,而中介者可以更好地管理和控制这些变化;
  • 需要在多个对象之间进行协调和通信,但是又不希望它们直接进行交互,以免产生复杂的耦合关系。

中介者模式的优点和缺点

        中介者模式的优点在于:

  • 能够减少类之间的依赖关系,实现类之间的解耦;
  • 中介者可以统一管理类之间的交互规则,方便修改和扩展;
  • 当一组对象之间的交互很复杂的时候,中介者模式能够简化这些交互,使之变得清晰明了。
  • 中介者对象可能会变得非常复杂,因为它需要管理所有相关类的交互;
  • 中介者对象的变更可能会影响到所有的相关类,这可能会增加系统的风险;
  • 如果不恰当使用中介者模式,可能会导致系统的设计变得更加复杂。

        然而,中介者模式也有一些缺点:

  • 中介者对象可能会变得非常复杂,因为它需要管理所有相关类的交互;
  • 中介者对象的变更可能会影响到所有的相关类,这可能会增加系统的风险;
  • 如果不恰当使用中介者模式,可能会导致系统的设计变得更加复杂。

总结

        中介者模式是一种软件设计模式,它的目的是将一组对象之间的交互抽象化到一个单独的对象中,使得各个对象不必直接交互,而只与这个中间对象发生交互。这种模式可以帮助我们减少类之间的依赖关系,实现类之间的解耦,并简化复杂的交互关系。

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

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

相关文章

设计模式JAVA

1 创建型 如何合理的创建对象&#xff1f; 1.1 单例模式 字面意思就是只能创建一个对象实例时使用。 例如&#xff0c;Windows中只能打开一个任务管理器&#xff0c;这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费&#xff0c;或出现各个窗口显示内容的不一致等…

Java学习 10.Java-数组习题

一、创建一个 int 类型的数组, 元素个数为 100, 并把每个元素依次设置为 1 - 100 代码实现 public static void main(String[] args) {int[] arrnew int[100];for (int i 0; i < arr.length; i) {arr[i]i1;}System.out.println(Arrays.toString(arr));} 运行结果 二、改变…

k8s-docker二进制(1.28)的搭建

二进制文件-docker方式 1、准备的服务器 角色ip组件k8s-master1192.168.11.111kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-master2192.168.11.112kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-node1192.168.11.113kubelet,kube-prox…

相机内外参实践之点云投影矢量图

目录 概述 涉及到的坐标变换 深度值可视化 3D点云的2D投影实现 实现效果 参考文献 概述 Camer的内外参在多模态融合中主要涉及到坐标系变换&#xff0c;即像素坐标、相机坐标以及其他坐标系。这篇就针对点云到图像的投影与反投影做代码实践&#xff0c;来构建一张具有深度…

【从0到1设计一个网关】上岸大厂的秘诀之一

文章目录 前言【从0到1设计一个网关】什么是网关&#xff1f;以及为什么需要自研网关&#xff1f;【从0到1设计一个网关】自研网关的设计要点以及架构设计【从0到1设计一个网关】自研网关的架构搭建【从0到1设计一个网关】网络通信框架Netty的设计【从0到1设计一个网关】整合Na…

LeetCode(2)移除元素【数组/字符串】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 27. 移除元素 1.题目 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原…

centos7安装linux版本的mysql

1.下载linux版本的mysql 进入mysql官网&#xff0c;点击社区版本下载&#xff1a; https://dev.mysql.com/downloads/mysql/ 选择版本&#xff0c;可以跟着我下面这个图进行选择&#xff0c;选择红帽版本的既可&#xff0c;都是linux版本的。 2.上传解压linux版本的mysql安装包…

Matlab的多项式留数与极点的计算

Matlab的多项式留数与极点的计算 以下面的多项式为例&#xff1a; 运算代码&#xff1a; clc clear closesyms p % 定义多项式 Zp(5*p^571*p^370*p)/(2*p^635*p^4117*p^236); % 提取分子与分母 [I,D]numden(Zp); Idouble(coeffs(I,p,"All"));%分子 Ddouble(coeffs…

报时机器人的rasa shell执行流程分析

本文以报时机器人为载体&#xff0c;介绍了报时机器人的对话能力范围、配置文件功能和训练和运行命令&#xff0c;重点介绍了rasa shell命令启动后的程序执行过程。 一.报时机器人项目结构 1.对话能力范围 (1)能够识别欢迎语意图(greet)和拜拜意图(goodbye) (2)能够识别时间意…

ROS 学习应用篇(三)话题Topic学习之自定义话题消息的类型的定义与调用

自定义消息类型的定义 Person.msg文件的定义&#xff08;数据接口文件的定义&#xff09; 创建msg文件 首先在功能包下新建msg文件夹&#xff0c;接着在该文件夹下创建文件。 定义msg文件内容 一个消息最重要的就是数据结构类型。这就需要引入一个msg文件&#xff0c;用于…

剑指offer(C++)-JZ21:调整数组顺序使奇数位于偶数前面(一)(算法-其他)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 输入一个长度为 n 整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&#xff0c;使得所有的奇数…

【React入门实战】实现Todo代办

文章目录 效果功能-状态管理相关接口定义相关方法定义 UIinput输入框&#xff1a;回车添加todo标题列表列表项Main 总体代码 非常简单入门的react-todo练习&#xff0c;代码写的很小白。 效果 技术栈&#xff1a;react-typeScript 数据分为代办Todo和已办完Done&#xff0c;可…