博文原址:折腾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. 文本分布式表示(二):用tensorflow和word2vec训练词向量

    看了几天word2vec的理论,终于是懂了一些.理论部分我推荐以下几篇教程,有博客也有视频: 1.<word2vec中的数学原理>:http://www.cnblogs.com/pegho ...

  2. Linux 系统调用过程详细分析

    内核版本:Linux-4.19 操作系统通过系统调用为运行于其上的进程提供服务. 那么,在应用程序内,调用一个系统调用的流程是怎样的呢? 我们以一个假设的系统调用 xyz() 为例,介绍一次系统调用的 ...

  3. laravel中如何利用反射实现依赖注入

    依赖注入 在一个类中经常会依赖于其他的对象,先看一下经典的写法 class Foo { public $bar; public function __construct() { $this->b ...

  4. ArcGIS JS API多线程克里金插值

        最近做关于雨量插值的项目,本来使用后台的GP工具做的,但是处理时间比较长需要十几秒钟左右,所以研究怎么通过前台来计算.     参考下克里金例子,思路是生成要计算区域的100乘以100网格,然 ...

  5. idea解决Maven jar依赖冲突(四)

    首先点击右侧的MavenProjects打开以下界面: 这个界面是maven的命令界面: 点击这个图标会进入如下界面: 左上角可以缩放,点击线可以取消冲突依赖,红色线为冲突依赖. 上图为无依赖冲突的s ...

  6. Visual Studio Code-批量添加或删除注释行

    小技巧一例,批量删除Visual Studio code或notepad++注解信息,便于读取有效代码或文本信息,具体操作如下: Visual Studio Code批量删除注解行信息: 在VS Co ...

  7. How to fix corrupt HDFS FIles

    1 问题描述 HDFS在机器断电或意外崩溃的情况下,有可能出现正在写的数据(例如保存在DataNode内存的数据等)丢失的问题.再次重启HDFS后,发现hdfs无法启动,查看日志后发现,一直处于安全模 ...

  8. iOS客户端图片智能裁剪

     概述 所谓智能裁剪其实就是按照指定尺寸裁剪或显示出包含图片核心特征的区域,目前很多智能裁剪都是在服务器端做的,在客户端需要访问时直接裁剪放到Redis或者提前裁剪好以备访问.但是找了一圈直接在iO ...

  9. 深入理解this关键字

    Java提供了一个this关键字,this关键字总是指向调用该方法的对象.根据this出现的位置的不同,this作为对象的默认引用有两种情形. 1)构造器中引用该构造器正在初始化的对象. 2)在方法中 ...

  10. HTML5+CSS3入门学习(一)——HTML5

    什么是 HTML5? HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML 的上一个版本诞生于 1999 年.自从那以后,Web 世界已经经历了巨变. HTML5 仍 ...