当前位置: 首页 > news >正文

设计模式(21)中介者模式

一、介绍:

1、定义:中介者模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介者对象来降低多个对象之间的耦合度。在中介者模式中,各个对象之间不直接进行通信,而是通过中介者对象进行协调和通信。

2、组成结构:

(1)抽象中介者(Abstract Mediator):定义了中介者对象的接口,用于协调各个同事对象之间的交互。

(2)具体中介者(Concrete Mediator):实现了抽象中介者接口,负责协调各个同事对象的交互,并了解各个同事对象的具体实现。

(3)抽象同事类(Abstract Colleague):定义了同事对象的接口,通常持有一个中介者对象的引用,用于与中介者进行通信。

(4)具体同事类(Concrete Colleague):实现了抽象同事类的接口,实现自身的业务逻辑,并通过中介者对象进行与其他同事对象的通信。

// 抽象中介者
interface Mediator {void send(String message, Colleague colleague);
}// 具体中介者
class ConcreteMediator implements Mediator {private Colleague colleague1;private Colleague colleague2;public void setColleague1(Colleague colleague1) {this.colleague1 = colleague1;}public void setColleague2(Colleague colleague2) {this.colleague2 = colleague2;}@Overridepublic void send(String message, Colleague colleague) {if (colleague == colleague1) {colleague2.receive(message);} else {colleague1.receive(message);}}
}// 抽象同事类
abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}public abstract void send(String message);public abstract void receive(String message);
}// 具体同事类
class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator mediator) {super(mediator);}@Overridepublic void send(String message) {mediator.send(message, this);}@Overridepublic void receive(String message) {System.out.println("ConcreteColleague1 Received: " + message);}
}class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}@Overridepublic void send(String message) {mediator.send(message, this);}@Overridepublic void receive(String message) {System.out.println("ConcreteColleague2 Received: " + message);}
}// 客户端
public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);mediator.setColleague1(colleague1);mediator.setColleague2(colleague2);colleague1.send("msg from Colleague1");colleague2.send("msg from Colleague2");}

3、优点:

(1)降低耦合度:中介者模式将对象之间的交互集中在中介者对象中,减少了对象之间的直接依赖和耦合度,使系统更加灵活、可扩展和易于维护。

(2)简化对象间的通信:中介者模式通过引入中介者对象,将对象间复杂的相互通信转变为对象与中介者之间的简单交互,简化了对象间的通信逻辑。

(3)集中控制逻辑:中介者模式将对象间的交互逻辑集中在中介者对象中,使得系统的控制逻辑更加清晰明确。通过定义中介者对象来协调对象间的交互,可以更方便地修改和扩展系统的行为。

(4)促进代码重用:中介者模式将公共的交互逻辑封装在中介者对象中,可以被多个对象共享和复用,避免了代码的重复编写,提高了代码的可维护性和可复用性。

 4、适用场景:

(1)当一个系统中对象之间存在复杂的相互关系,导致对象间的交互逻辑难以维护和扩展时,可以考虑使用中介者模式来简化交互逻辑。

(2)当一个对象需要对多个对象进行操作或通知时,可以引入中介者模式来集中管理这些对象之间的交互。

(3)当系统中的对象之间存在循环依赖关系,不方便直接进行交互时,可以通过引入中介者对象来解决循环依赖问题。

二、demo:

1、房租中介:三个房东、三个租客。房东类和租客类互相影响,称为同事类。

(1)抽象同事类

import java.util.Objects;/*** 抽象同事类(这里指房东、租客),有用户名称,以及消息发送、接收功能*/
public abstract class Colleague {//租客、房东 都认识中介Mediator mediator;public String userName;public Colleague(String userName, Mediator mediator){this.userName = userName;this.mediator = mediator;}//这里对userName做equals和hashCode,是为了后面可以用contains判断方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Colleague colleague = (Colleague) o;return Objects.equals(userName, colleague.userName);}@Overridepublic int hashCode() {return Objects.hash(userName);}public void sendMsg(String msg){System.out.println("我"+this.userName+"发送消息");}public void receiveMsg(String msg,Colleague fromColleague){}
}

(2)具体同事类,房东和租客

//房东类
public class LandlordColleague extends Colleague{public LandlordColleague(String userName, Mediator mediator) {super(userName,mediator);}//发送消息,需要通知谁 谁可以收到由中介完成@Overridepublic void sendMsg(String msg) {super.sendMsg(msg);mediator.notice(msg,this);}//收到中介发送的消息@Overridepublic void receiveMsg(String msg,Colleague fromColleague) {System.out.println("房东"+this.userName+"收到"+fromColleague.userName+"发送的消息"+msg);}
}
import java.util.List;//租客同事类
public class TenantColleague extends Colleague {public TenantColleague(String userName, Mediator mediator) {super(userName,mediator);}//发送消息,谁可以收到(所有房东)由中介完成@Overridepublic void sendMsg(String msg) {super.sendMsg(msg);mediator.notice(msg,this);}//收到消息@Overridepublic void receiveMsg(String msg,Colleague fromColleague) {System.out.println("租客"+this.userName+"收到"+fromColleague.userName+"发送的消息"+msg);}
}

(3)抽象中介

//抽象中介
public interface Mediator {//通知void notice(String msg,Colleague fromColleague);
}

(4)具体中介

import java.util.ArrayList;
import java.util.List;/*** 房租中介*/
public class RentMediator implements Mediator{//所有租客List<Colleague> tenantColleagues = new ArrayList<>();//所有房东List<Colleague> landlordColleagues = new ArrayList<>();//添加房东void addLandlord(Colleague colleague){this.landlordColleagues.add(colleague);}//添加租客void addTenantColleague(Colleague colleague){this.tenantColleagues.add(colleague);}/*** 通知* 通知所有房东or 租客* @param msg* @param fromColleague*/@Overridepublic void notice(String msg, Colleague fromColleague) {//房东发的,通知所有租客if(landlordColleagues.contains(fromColleague)){for(Colleague colleague : tenantColleagues){colleague.receiveMsg(msg,fromColleague);}}//租客发的,通知所有房东if(tenantColleagues.contains(fromColleague)){for(Colleague colleague : landlordColleagues){colleague.receiveMsg(msg,fromColleague);}}}
}

客户端:

public class Test {public static void main(String args[]){RentMediator rentMediator = new RentMediator();//房东管理LandlordColleague landlordColleague1 = new LandlordColleague("房东1",rentMediator);LandlordColleague landlordColleague2 = new LandlordColleague("房东2",rentMediator);LandlordColleague landlordColleague3 = new LandlordColleague("房东3",rentMediator);rentMediator.addLandlord(landlordColleague1);rentMediator.addLandlord(landlordColleague2);rentMediator.addLandlord(landlordColleague3);//租客管理TenantColleague tenantColleague1 = new TenantColleague("租客1",rentMediator);TenantColleague tenantColleague2 = new TenantColleague("租客2",rentMediator);TenantColleague tenantColleague3 = new TenantColleague("租客3",rentMediator);rentMediator.addTenantColleague(tenantColleague1);rentMediator.addTenantColleague(tenantColleague2);rentMediator.addTenantColleague(tenantColleague3);//tenantColleague2.sendMsg("寻找三室房源");System.out.println("******");landlordColleague3.sendMsg("发布新房源");}
}输出:
我租客2发送消息
房东房东1收到租客2发送的消息寻找三室房源
房东房东2收到租客2发送的消息寻找三室房源
房东房东3收到租客2发送的消息寻找三室房源
******
我房东3发送消息
租客租客1收到房东3发送的消息发布新房源
租客租客2收到房东3发送的消息发布新房源
租客租客3收到房东3发送的消息发布新房源

相关文章:

设计模式(21)中介者模式

一、介绍&#xff1a; 1、定义&#xff1a;中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;它通过引入一个中介者对象来降低多个对象之间的耦合度。在中介者模式中&#xff0c;各个对象之间不直接进行通信&#xff0c;而是通过中介者对象…...

JVM虚拟机:通过一个例子解释JVM中栈结构的使用

代码 代码解析 main方法执行&#xff0c;创建栈帧并压栈。 int d8&#xff0c;d为局部变量&#xff0c;是基础类型&#xff0c;它位于虚拟机栈的局部变量表中 然后创建了一个TestDemo的对象&#xff0c;这个对象在堆中&#xff0c;并且这个对象的成员变量&#xff08;day&am…...

会自动写代码的AI大模型来了!阿里云推出智能编码助手通义灵码

用大模型写代码是什么样的体验&#xff1f;10月31日&#xff0c;杭州云栖大会上&#xff0c;阿里云对外展示了一款可自动编写代码的 AI 助手&#xff0c;在编码软件的对话窗口输入“帮我用 python 写一个飞机游戏”&#xff0c;短短几秒&#xff0c;这款名为“通义灵码”的 AI …...

如何公网远程访问本地WebSocket服务端

本地websocket服务端暴露至公网访问【cpolar内网穿透】 文章目录 本地websocket服务端暴露至公网访问【cpolar内网穿透】1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功…...

python 练习 在列表元素中合适的位置插入 输入值

目的&#xff1a; 有一列从小到大排好的数字元素列表&#xff0c; 现在想往其插入一个值&#xff0c;要求&#xff1a; 大于右边数字小于左边数字 列表元素&#xff1a; [1,4,6,13,16,19,28,40,100] # 方法&#xff1a; 往列表中添加一个数值&#xff0c;其目的方便元素位置往后…...

企业级JAVA、数据库等编程规范之命名风格 —— 超详细准确无误

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信你对这两篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc; 表白墙/留言墙 —— 初级SpringBoot项目&#xff0c;练手项目前后端开发(带完整源码) 全方位全步骤手把手教学 &#x1f4dc; 用户登录前后端…...

有什么可以自动保存微信收到的图片和视频的方法么

8-1 在一些有外勤工作的公司里&#xff0c;经常会需要在外面工作的同事把工作情况的图片发到指定微信或者指定的微信群里&#xff0c;以记录工作进展等&#xff0c;或者打卡等&#xff0c;对于外勤人员来说&#xff0c;也就发个图片的事&#xff0c;但是对于在公司里收图片的人…...

面试算法46:二叉树的右侧视图

题目 给定一棵二叉树&#xff0c;如果站在该二叉树的右侧&#xff0c;那么从上到下看到的节点构成二叉树的右侧视图。例如&#xff0c;图7.6中二叉树的右侧视图包含节点8、节点10和节点7。请写一个函数返回二叉树的右侧视图节点的值。 分析 既然这个题目和二叉树的层相关&a…...

vite配置terser,压缩代码及丢弃console

...

R语言使用surveyCV包对NHANES数据(复杂调查加权数据)进行10折交叉验证

美国国家健康与营养调查&#xff08; NHANES, National Health and Nutrition Examination Survey&#xff09;是一项基于人群的横断面调查&#xff0c;旨在收集有关美国家庭人口健康和营养的信息。 地址为&#xff1a;https://wwwn.cdc.gov/nchs/nhanes/Default.aspx 既往咱们…...

WOS与CNKI数据库的citespace分析教程及常见问题解决

本教程为面向新手的基于citespace的数据可视化教程&#xff0c;旨在帮助大家更快了解行业前沿的研究内容。 获取最新版本的citespace软件 在citespace官网下载最新的版本&#xff08;如果是老版本&#xff0c;可能会提示让你去官网更新为最新版&#xff0c;老版本不再提供服务…...

NEFU数字图像处理(三)图像分割

一、图像分割的基本概念 1.1专有名词 前景和背景 在图像分割中&#xff0c;我们通常需要将图像分为前景和背景两个部分。前景是指图像中我们感兴趣、要分割出来的部分&#xff0c;背景是指和前景不相关的部分。例如&#xff0c;对于一张人物照片&#xff0c;人物就是前景&…...

UEditorPlus v3.6.0 图标补全,精简代码,快捷操作重构,问题修复

UEditor是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更符…...

C++ Set

定义 set不同于vector,strin,list这种存储容器&#xff0c;set是一种关联式容器&#xff0c;底层是搜二叉&#xff1b; 功能 set可以确定唯一的值&#xff0c;可以排序去重。 接口 insert() #include <iostream> #include<set> using namespace std;int main…...

基于知识库的chatbot或者FAQ

背景 最近突然想做一个基于自己的知识库&#xff08;knowlegebase&#xff09;的chatbot或者FAQ的项目。未来如果可以在公司用chatgpt或者gpt3.5之后的模型的话&#xff0c;还可以利用gpt强大的语言理解力和搜索出来的用户问题的相关业务文档来回答用户在业务中的问题。 Chat…...

ZOC8 for Mac:超越期待的终端仿真器

在Mac上&#xff0c;一个优秀的终端仿真器是每位开发者和系统管理员的必备工具。ZOC8&#xff0c;作为一款广受好评的终端仿真器&#xff0c;以其强大的功能和易用性&#xff0c;已经在Mac用户中积累了良好的口碑。本文将为您详细介绍ZOC8的各项特性&#xff0c;以及为什么它会…...

织梦dedecms后台档案列表显示空白或显示不了文章的解决方法

织梦dedecms后台档案列表显示空白或显示不了文章的解决方法 dede/content_list.php空白解决方法如下 dede/content_list.php空白 在DEDE后台可以查看栏目文章&#xff0c;但是所有档案列表却为空白或者显示不了文章,如图所示&#xff1a; 后来找到dede/content_list.php,看了下…...

10本值得阅读的量化交易书籍

什么是量化交易&#xff1f; 量化交易是利用数学模型或算法来创建交易策略并进行交易。量化交易通常由大型机构交易员或对冲基金雇用&#xff0c;他们雇用大量的博士和工程师团队。从历史上看&#xff0c;量化交易领域一直非常隐秘&#xff0c;有效的想法往往受到公司的严密保…...

c++通过对象的地址初始化指针,需要对指针进行释放么(企业链表衍生)

在C中&#xff0c;如果你通过对象的地址来初始化指针&#xff0c;通常情况下是不需要手动释放指针的。这是因为对象的生存期与指针所指向的对象的生存期相关联。当对象超出其作用域或被销毁时&#xff0c;指向该对象的指针也会自动成为悬挂指针&#xff0c;这种情况下再访问该指…...

CentOS安装MySQL

参考官方链接&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/linux-installation-rpm.html CentOS版本 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) 下载MySQL安装包&#xff08;版本&#xff1a;8.0.35&#xff09; 访问地址…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...