Java设计模式之中介者模式
作者:tianClassmate 发布时间:2022-11-16 22:39:01
在我们实际业务中,可能存在多个类之间相互调用,形成了一个复杂的网状结构。这时候就需要有一种模式去“捋顺”他们之间的关系,引出一个中间者让类之间不再相互调用,该模式就是我们今天的主人公——中介者模式。
一、概念理解
我们先看中介者模式的官方概念:用一个中介者对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互。
大白话解释就是,引入一个“中介”,用于协调各个对象的关系,各个对象之间不用那么直白的直接调,对象只需要调用中介的方法,中介内部进行逻辑判断,由中介去调用各个对象的方法。
概念基本清楚以后接着看中介者模式包含的角色都有哪些:
中介者角色、各个对象角色是必须的,在面向接口编程原则下,中介者和对象应该抽离出来接口,于是在中介者模式的结构中就包括四种角色(各个对象角色称为同事):
1.中介者(Mediator):中介者是一个接口,该接口定义了用于同事(Colleague)对象之间进行通信的方法;
2.具体中介者(ConcreteMediator):具体中介者是实现中介者接口的类。具体中介者需要包含所有具体同事(ConcreteColleague)的引用,并通过实现中介者接口中的方法来满足具体同事之间的通信要求;
3.同事(Colleague):一个接口,规定了具体同事需要实现的方法;
4.具体同事(ConcreteColleague):实现了同事接口的类。具体同事需要包含具体中介者的引用,一个具体同事需要和其他具体同事交互时,只需将自己的请求通知给它所包含的具体中介者的引用。
如果在一个业务场景中,一个公司有很多同事,同事1 管理的有自己的数据,有时候也会调用同事2的数据。
在中介者模式下,同事1和同事2 之间不再相互调用,由中介者统一调用,同事类中要持有中介者对象,中介者方法中要有判断属于哪个角色的方法。
基于四个角色,实现初试的demo。
读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云。
本地源码下载
二、案例实现
抽象同事类:
抽象同事中要持有中介者的引用
/**
* 抽象同事类
* @author tcy
* @Date 14-09-2022
*/
public abstract class Colleague {
//抽象中介者引用
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
//数据更新方法
public abstract void update();
//数据更改方法
public abstract void changed();
}
具体同事类1、2:
具体同事类除了有自己的业务逻辑之外,应该还有额外调用中介者的方法
/**
* 具体同事2
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator)
{
super(mediator);
}
//自己的方法
@Override
public void update()
{
System.out.println("更新同事类2");
}
//调用同事的方法
@Override
public void changed()
{
System.out.println("同事类2数据更改");
mediator.operation(this);
}
}
/**
* 具体同事1
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteColleague1 extends Colleague{
public ConcreteColleague1(Mediator mediator)
{
super(mediator);
}
@Override
public void update()
{
System.out.println("更新同事类1");
}
@Override
public void changed()
{
System.out.println("同事类1数据更改");
mediator.operation(this);
}
}
抽象中介者:
抽象中介者应该是持有所有同事对象,并且应该有一个方法去调用别的同事
/**
* 抽象中介者
*/
public abstract class Mediator {
protected ArrayList<Colleague> colleagues = new ArrayList<>();
public void add(Colleague colleague)
{
colleagues.add(colleague);
}
public abstract void operation(Colleague colleague);
}
具体中介者:
具体中介者实现抽象中介者的方法,根据条件调用不同的同事
/**
* 具体中介者
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteMediator extends Mediator {
@Override
public void operation(Colleague colleague)
{
if(colleague instanceof ConcreteColleague1)
colleagues.get(1).update();
else if(colleague instanceof ConcreteColleague2)
colleagues.get(0).update();
}
}
三、中介者模式源码中的应用
中介者模式的典型应用就是Jdk中的Timer 类。
我们知道Timer 类的主要作用是用于定时任务,定时任务之间会存在通信问题,如果众多的定时任务都相互通信,那对于系统对象间的引用来说就是一灾难,引出中介者模式就是理所应当的了。
当有新的任务加入到队列中,均把该任务当做同事,各个任务之间的通信都是由Timer 类来完成,Timer 类就相当于中介者的角色。
我们知道,Timer 类实现定时任务的主要方法就是schedule(),schedule()有一堆的重载方法。
我们点开任意的schedule方法。
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
均调用了sched()私有方法。
我们重点看红线标记的代码块,将任务放入一个 队列中,这个队列和我们例子中的Arrlist是一个作用。
private final TaskQueue queue = new TaskQueue();
判断以后,调用Object的notify()方法,进行线程间的通信。
试想一下,如果没有这个中介,每个定时任务都手动的调用notify()方法,该有多么痛苦。
四、总结
网上讲解设计模式的文章很多,能把中介模式讲清楚很简单,但能说明白何时使用合适的设计模式却是难上加难。在前三章设计模式的基础之上,第四章总结看完,希望读者能对正确使用设计模式有一个清晰的轮廓。
很多网上的博客都说要职责清晰才可使用中介者模式,如果类的职责是混乱的,那中介者的逻辑写起来就很难受。还有多个对象间耦合严重,类图之间出现了网状结构,这时候就可以考虑中介者模式了,如果仅仅是为了使用中介者模式而使用,那就得不偿失了。
中介者的优点突出,中介者模式的出现会让网状结构,有序的转化为星状结构。能有序降低类的复杂度,将多对多的关系转化为一对多,降低了类之间的耦合。
缺点也很明显,会增加类的个数,同事类越多,中介者的逻辑也就越复杂。
来源:https://www.cnblogs.com/tianClassmate/p/16695471.html
猜你喜欢
- 本文实例为大家分享了Unity实现截图功能的具体代码,供大家参考,具体内容如下一、使用Unity自带APIusing UnityEngine
- 唉!我还真是在面试中学习新东东啊,一个公司刚刚给了个测试,不过我很奇怪的是为什么web developer的职位居然考java的反射机制题,
- 1,创建存储过程create proc Pro_Login(@UserName nvarchar(10),@PassWord nvarcha
- Android Studio 3.6正式版已经发布https://android-developers.googleblog.com/202
- 问题现象今天在做一个需求:将存入数据库中的数据读到后解析成list遍历分析数据格式:"[1677660600000, 167766
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- SpringBoot下载Excel文件文件损坏我把模板文件放在了resources目录下maven插件打包项目的时候,默认会压缩resour
- 通常我们遇到的图片缩放需求,都是图片基于屏幕自适应后,进行缩放和移动,且图片最小只能是自适应的大小。最近遇到一个需求,要求图片只能在屏幕内缩
- 前言相信大家都知道Android滚动控件的实现方式有很多, 使用RecyclerView也比较简单. 做了一个简单的年龄滚动控件, 让我们来
- 一、编译步骤解压下载的GDAL源程序,并在命令行中切换到解压目录。tar -xzvf gdal-2.1.3.tar.gzcd gdal-2.
- @Profile注解详解@Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;开发环境develop
- 基础知识介绍: @RequestBody主要用来接收前端传递给后端的json字符串中的
- 这篇文章主要介绍了Spring ApplicationListener * 用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具
- 本文实例为大家分享了C语言实现简单版三子棋的具体代码,供大家参考,具体内容如下游戏的主函数设计:1.打印出可以让玩家选择游戏开始和退出的菜单
- Android ScrollView无法填充满屏幕的解决办法ScrollView滚动视图是指当拥有很多内容、屏幕显示不完时、需要通过滚动跳来
- 一、关键字关键字:被Java语言赋予特定含义的单词。组成关键字的字母全部小写。注:goto和const作为保留字存在,目前并不使用。main
- 一、 Sharding-jdbc简介“Sharding-jdbc是开源的数据库操作中间件;定位为轻量级Java框架,在Java的JDBC层提
- 目录1.下列关于计算机系统和Java编程语言的说法,正确的是()2.变量a是一个64位有符号的整数,初始值用16进制表示为:0Xf00000
- 1.插入排序这个打麻将或者打扑克的很好理解, 比如有左手有一副牌1,2,4,7 ,来一张3的牌, 是不是就是手拿着这张牌从右往左插到2,4之
- 面向对象编程(Object Oriented Programming)有三大特性:封装、继承、多态。在这里,和大家一起加深对三者的理解。封装