博文原址:折腾Java设计模式之中介者模式

中介者模式

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

通俗点来讲就是提供一个中介平台,说到平台,那其实很容易联系到我们很熟悉的房地产中介。我们可以直接通过这个平台得到我们想要的信息,不用对象自身与其他对象交互。

买房子租房子就不需要去找房东,只需要在中介那里获取相应的房产信息。如下图那样,两方只需要找中介即可。

再来看一张对比图。

有没有感觉没有使用之前,对象间互相依赖互相调用,错综复杂,盘根错节,当加入中介者后,对象间的关系一目了然,清晰明了。由中介对象来封装一系列对象之间的交互关系。中介者使各个对象之间不需要显式地相互引用,从而使耦合性降低,而且可以独立地改变它们之间的交互行为。

中介者模式UML图

UML类图和时序图

collague1和collague2类不直接相互依赖,它们是用起控制和协调交互作用的公共中介接口(mediate()方法),这使它们有独立交互的执行方式。mediate1类实现collague1和collague2之间的依赖。

中介者模式角色

抽象中介者(Mediator): 定义了同事对象到中介者对象之间的接口。

具体中介者(ConcreteMediator): 实现抽象中介者的方法,它需要知道所有的具体同事类,同时需要从具体的同事类那里接收信息,并且向具体的同事类发送信息。

抽象同事类(Colleague): 定义了中介者对象的接口,它只知道中介者而不知道其他的同事对象。

具体同事类(ConcreteColleague) : 每个具体同事类都只需要知道自己的行为即可,但是他们都需要认识中介者。

示例代码

源码地址

抽象中介者

@Slf4j
public abstract class Mediator { /**
* 房东map
*/
protected Map<People, Message> landlordMap = Maps.newHashMap(); /**
* 租户列表
*/
protected List<People> renterList = Lists.newArrayList(); /**
* 注册房东信息
*
* @param landlord 房东
* @param message 房屋信息
*/
public void registerLandlord(People landlord, Message message) {
landlordMap.put(landlord, message);
log.info("中介信息:房东|{}|加入到中介平台,房屋信息:{}", landlord.getName(), message);
} /**
* 变更房东信息
*
* @param landlord 房东
* @param message 房屋信息
*/
protected void modifyLandlordInfo(People landlord, Message message) {
landlordMap.put(landlord, message);
log.info("中介信息:房东|{}|修改他在中介平台的房屋信息,现房屋信息:{}", landlord.getName(), message);
} /**
* 注册租户信息
*
* @param renter 租户
*/
public void registerRenter(People renter) {
renterList.add(renter);
log.info("中介信息:租户|{}|来中介平台租房", renter.getName());
} /**
* 声明抽象方法 由具体中介者子类实现 消息的中转和协调
*/
public abstract void operation(People people, Message message); }

抽象同事类

@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class People { private Mediator mediator; private String name; /**
* 向中介发送消息
*/
protected abstract void sendMessage(Message message); /**
* 从中介获取消息
*/
protected abstract void getMessage(Message message);
}

具体同事类 房东和租户

@Slf4j
public class Landlord extends People { public Landlord(Mediator mediator, String name) {
super(mediator, name);
} @Override
protected void sendMessage(Message message) {
getMediator().operation(this, message);
} @Override
protected void getMessage(Message message) {
log.info("房东|{}|从中介获取到租户的信息:{}", getName(), message);
}
}
@Slf4j
public class Renter extends People { public Renter(Mediator mediator, String name) {
super(mediator, name);
} @Override
protected void sendMessage(Message message) {
getMediator().operation(this, message);
} @Override
protected void getMessage(Message message) {
log.info("租户|{}|从中介获取到房东的信息:{}", getName(), message);
}
}

具体中介者

public class RealEstateAgent extends Mediator {

    @Override
public void operation(People people, Message message) {
if (people instanceof Renter) {
// 将租户的租房条件信息发送给房东们
landlordMap.keySet().forEach(landlord -> landlord.getMessage(message)); // 租户收到中介那里房东的房屋信息
landlordMap.values().forEach(messages -> people.getMessage(messages));
} else if (people instanceof Landlord) {
// 将房东的房屋信息发送给租户们
renterList.forEach(renter -> renter.getMessage(message));
// 变更中介里的房东房屋信息
modifyLandlordInfo(people, message);
}
}
}

客户端

@Slf4j
public class Client { public static void main(String[] args) {
Mediator mediator = new RealEstateAgent();
People laoWang = new Landlord(mediator, "老王");
People laoLee = new Landlord(mediator, "老李");
People laoBai = new Landlord(mediator, "老白"); People xiaoSan = new Renter(mediator, "小3");
People xiaoWang = new Renter(mediator, "小王"); mediator.registerLandlord(laoWang, Message.builder().msg("我这有2500的房子,市中心").build());
mediator.registerLandlord(laoBai, Message.builder().msg("我这有2000的房子,地铁旁").build());
mediator.registerLandlord(laoLee, Message.builder().msg("我这有2000的房子,落地阳台,大空间,采光好,地铁旁").build()); mediator.registerRenter(xiaoSan); log.info("小3开始找房子");
xiaoSan.sendMessage(Message.builder().msg("想找个月租2000块的房子,靠近地铁").build());
log.info("没过多久---------老白升级了房屋信息");
laoBai.sendMessage(Message.builder().msg("我这有2000的房子,地铁旁,我又加了空调和热水器").build());
mediator.registerRenter(xiaoWang);
log.info("小王开始找房子");
xiaoWang.sendMessage(Message.builder().msg("想找个月租2500块的房子,靠近地铁").build());
log.info("没过多久---------老李也升级了房屋信息");
laoBai.sendMessage(Message.builder().msg("我这有2000的房子,落地阳台,大空间,采光好,地铁旁,我也加了空调和热水器").build()); }
}

最终出效果的如下

现在我来分析下里面各个角色的作用:

首先先分析两个抽象类。抽象同事类,含有名称和中介者的引用,有2个方法从中介拿信息和发信息给中介。抽象中介者,其中含有房东的map信息,key为房东数据,value为房东的房屋信息,用来房东注册和房东房屋信息变更;租户的列表信息,供租户注册,同时还有个协调方法,用于协调房东和租户。

具体抽象类(房地产中介),实现了抽象中介者的协调方法,当租户发送消息时,将租户的租房条件信息发送给所有房东们同时该租户收到中介那里所有房东的房屋信息;当房东发送消息时,将房东的房屋信息发送给所有租户们同时变更中介里的改房东房屋信息。

具体同事实现类(房东和租户),实现了抽象同事类的读取消息方法和发送消息方法(该房屋就是依靠中介者的协调方法来实现)。

JDK中的应用

通过使用一个中间对象来进行消息分发以及减少类之间的直接依赖。

java.util.Timer

java.util.concurrent.Executor#execute()

java.util.concurrent.ExecutorService#submit()

java.lang.reflect.Method#invoke()

总结

优点

使用中介者模式可以把对个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合。

中介者模式可以将原先多对多的同事对象关系变成中介者对象一对多同事对象的关系,这样会让对象之间的关系更容易理解和实现。

同事对象之间的交互都被封装到中介者对象里面集中管理,集中了控制交互。当交互发生改变时,着重修改的是中介者对象。当需要扩展中介者对象时,其他同事对象不需要做修改。

缺点

如果同事对象多了,交互也复杂了。中介者会庞大,变得复杂难以维护。

参考

中介者模式|菜鸟教程

Mediator pattern

细数JDK里的设计模式

JAVA设计模式之 中介者模式【Mediator Pattern】

欢迎关注

折腾Java设计模式之中介者模式的更多相关文章

  1. 从中国加入WTO来看Java设计模式:中介者模式

    目录 应用场景 中介者模式 定义 意图 主要解决问题 何时使用 优缺点 世界贸易组织WTO 应用场景 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象 想通过一个 ...

  2. Java 设计模式之中介者模式

    本文继续23种设计模式系列之中介者模式.   定义 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互.   角色 抽象中介者: ...

  3. java设计模式之中介者模式

    中介者模式 用一个中介对象来封装一系列的对象交互.中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 中介者模式UML图 中介者模式代码 package com ...

  4. Java 设计模式 之 中介者模式(Mediator)

    中介者的功能非常简单,就是封装对象之间的交互. 如果一个对象的操作会引起其他相关对象的变化,或者是某个操作需要引起其他对象的后续或连带操作,而这个对象又不希望自己来处理这些关系,那么久可以找中介者,把 ...

  5. 18.java设计模式之中介者模式

    基本需求 智能家庭包括各种设备,闹钟.咖啡机.电视机.窗帘等 要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为:闹铃响起->咖啡机开始做咖啡->窗帘自动落下-> ...

  6. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

  7. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  8. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  9. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

随机推荐

  1. Docker最全教程——Redis容器化以及排行榜实战(十三)

    前言 容器教程的路还很长,笔者尽量根据实践来不断地完善.由于在编写的过程中还会有完善和补充,后续可能会以番外来补充. 接下来会分享TeamCity.树莓派等内容,节奏可能会有点跳脱. 另外,长沙.NE ...

  2. 记录Ocelot + SignalR 多服务端测试

    前言 分两个项目,一个Gatway,一个SignalR 贴代码 1.Gatway 1.引用Ocelot 2.添加一点点代码 Startup.cs 3.简单配置ocelot ocelot.json { ...

  3. asp.net core系列 59 Ocelot 构建基础项目示例

    一.入门概述 从这篇开始探讨Ocelot,Ocelot是一个.NET API网关,仅适用于.NET Core,用于.NET面向微服务/服务的架构中.当客户端(web站点.ios. app 等)访问we ...

  4. “崩溃了?不可能,我全 Catch 住了” | Java 异常处理

    前言 今天我们来讨论一下,程序中的错误处理. 在任何一个稳定的程序中,都会有大量的代码在处理错误,有一些业务错误,我们可以通过主动检查判断来规避,可对于一些不能主动判断的错误,例如 RuntimeEx ...

  5. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  6. SpringCloud-分布式链路跟踪配置详解

    SpringCloud-分布式链路跟踪 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:作者使用IDEA + Gradle 注:需要有一定的java SpringBoot and ...

  7. 个人整理的 Windows 下 .NET 开发必装的软件

    注: 最后更新时间:2019-03-15 一..NET 开发 1. 必装 软件名称 说明 下载地址 JetBrains Toolbox JetBrins 全家桶管理工具. 下载地址 JetBrains ...

  8. CAP 2.3版本发布,支持 MongoDB

    前言 经过2个月的调整及测试,CAP 2.3 版本终于发布了,这个版本最大的特性就是对于 MongoDB 的支持,感谢博客园团队的keke同学对于 MongoDB 支持所提供的 PR,相信随着博客园的 ...

  9. npm 使用 taobao 的镜像后,无法 login & publish

    使用 npm adduser,添加用户之后,没有异常消息,然后使用 npm publish 发布,却报错: 401 原来是 npm 使用 taobao 的镜像后,需要指定 --registry htt ...

  10. SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确

    最近在查询SQL时遇到SQL文件错误,可能是文件数据已损坏.解决过程分享给大家. 问题描述 消息 824,级别 24,状态 2,第 1 行SQL Server 检测到基于一致性的逻辑 I/O 错误 p ...