中介者模式mediator---JDK源码中的体现
Posted 高高for 循环
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中介者模式mediator---JDK源码中的体现相关的知识,希望对你有一定的参考价值。
中介者模式 mediator
中介者模式(Mediator Pattern)又称为调节者模式 或者 调停者模式,是用来降低多个对象和类之间的通信复杂性。
意图:
- 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使各个对象不需要显示的相互作用,达到松耦合的目的,使得维护更加容易。
主要解决:
- 对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
何时使用:
- 多个类相互耦合,形成了网状结构。
为什么需要中介者模式?
微服务举例
- 我们以微服务为例,微服务刚开始诞生的时候是下面这个现象:
- 各个微服务之间互相依赖,整个依赖关系形成了网状,关系错综复杂,非常难以管理。所以后面就有了注册中心,
注册中心就可以理解为一个中介者:
消息队列MQ 也可以理解为一个中介者:
中介者模式角色
抽象中介者(Mediator):
1.抽象中介者(Mediator)角色:
- 它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2.具体中介者(ConcreteMediator)角色:
- 实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
3.抽象同事类(Colleague)角色:
- 定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4.具体同事类(Concrete Colleague)角色:
- 是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
案例:
抽象中介接口 :Mediator
public interface Mediator {
void register(Colleague colleague);//注册
void relay(Colleague colleague,String msg);//转发
}
具体中介类 :ConcreteMediator
import java.util.ArrayList;
import java.util.List;
public class ConcreteMediator implements Mediator {
//创建一个list来管理同事类
private List<Colleague> list = new ArrayList<Colleague>();
@Override
public void register(Colleague colleague) {
//list是否包含colleague
if(!list.contains(colleague)){
//添加并设置中介类
list.add(colleague);
colleague.setMedium(this);
}
}
@Override
public void relay(Colleague colleague, String msg) {
//遍历客户
for (Colleague cl : list) {
//如果不为发送者,则进行接收
if(!cl.equals(colleague)){
cl.recive(msg);
}
}
}
}
抽象同事接口 :Colleague
public interface Colleague {
void setMedium(Mediator mediator); //注册
void recive(String msg);//接收
void send(String msg);//发送
}
具体同事类1:ConcreteColleague1
public class ConcreteColleague1 implements Colleague {
protected Mediator mediator;
@Override
public void setMedium(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void recive(String msg) {
System.out.println("具体同事类1收到请求:"+msg);
}
@Override
public void send(String msg) {
System.out.println("具体同事类1发出请求:"+msg);
mediator.relay(this,msg);//请中介者转发
}
}
具体同事类2:ConcreteColleague2
public class ConcreteColleague2 implements Colleague {
protected Mediator mediator;
@Override
public void setMedium(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void recive(String msg) {
System.out.println("具体同事类2收到请求:"+msg);
}
@Override
public void send(String msg) {
System.out.println("具体同事类2发出请求:"+msg);
mediator.relay(this,msg);//请中介者转发
}
}
测试类:
public class MediatorTest {
public static void main(String[] args) {
//创建中介类
Mediator mediator = new ConcreteMediator();
//创建客户
Colleague colleague1 = new ConcreteColleague1();
Colleague colleague2 = new ConcreteColleague2();
//注册
mediator.register(colleague1);
mediator.register(colleague2);
colleague1.send("你好!");
System.out.println("----------------------");
colleague2.send("我很好!");
}
}
另 优化:
在实际开发中,通常采用以下两种方法来简化中介者模式,使开发变得更简单。
- 不定义中介者接口,把具体中介者对象实现成为单例。
- 同事对象不持有中介者,而是在需要的时直接获取中介者对象并调用。
如图所示是简化中介者模式的结构图:
package 中介模式;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 简单中介者模式
*/
class SimpleMediator {
private static SimpleMediator smd = new SimpleMediator();
private List<SimpleColleague> colleagues=new ArrayList<SimpleColleague>();
//私有自身
private SimpleMediator(){}
//获取自身
public static SimpleMediator getMedium(){
return smd;
}
//注册
public void register(SimpleColleague colleague){
//如果不包含则添加
if(!colleagues.contains(colleague)){
colleagues.add(colleague);
}
}
//转发
public void relay(SimpleColleague colleague){
for (SimpleColleague simpleColleague : colleagues) {
if(!colleague.equals(simpleColleague)){
simpleColleague.receive();
}
}
}
}
/**
* @Description: 抽象同事类
*/
interface SimpleColleague {
void receive();
void send();
}
/**
* @Description: 具体同事类1
*/
class SimpleConcreteColleague1 implements SimpleColleague {
SimpleConcreteColleague1(){
SimpleMediator smd=SimpleMediator.getMedium();
smd.register(this);
}
@Override
public void receive() {
System.out.println("同事1接收信息");
}
@Override
public void send() {
//需要才使用
SimpleMediator smd = SimpleMediator.getMedium();
System.out.println("同事1发送信息");
smd.relay(this); //请中介者转发
}
}
/**
* @Description: 具体同事类2
*/
class SimpleConcreteColleague2 implements SimpleColleague {
SimpleConcreteColleague2(){
SimpleMediator smd=SimpleMediator.getMedium();
smd.register(this);
}
@Override
public void receive() {
System.out.println("同事2接收信息");
}
@Override
public void send() {
//需要才使用
SimpleMediator smd = SimpleMediator.getMedium();
System.out.println("同事2发送信息");
smd.relay(this); //请中介者转发
}
}
public class SimpleMediatorTest {
public static void main(String[] args) {
SimpleColleague simpleColleague1 = new SimpleConcreteColleague1();
SimpleColleague simpleColleague2 = new SimpleConcreteColleague2();
simpleColleague1.send();
simpleColleague2.send();
}
}
总结
1 优点 :
1、降低了类的复杂度,将一对多转化成了一对一。
2、各个类之间的解耦。
3、符合迪米特原则。
2 缺点 :
1、中介者会庞大,变得复杂难以维护。
2、新增一个对象类,需要修改抽象中介者和具体中介者类。
3 使用场景 :
调度中心:统一分配资源的场景都可以使用中介模式,比如线程池
注册中心: 通过中介者登记并提供服务
媒体网关: 通过中介者进行消息转发
4 注意事项 :
不应当在职责混乱的时候使用。
中介者模式在JDK源码中应用
打开 JDK 中的 Timer 类,查看 Timer 类的结构,会发现 Timer 类中有很多 schedule() 重载方法,如下图所示。
任意点开其中一个方法,会发现所有方法最终都调用了私有的 sched() 方法,源码如下。
public class Timer {
...
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
...
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
...
}
- 不论是什么样的任务加入到队列中,我们都把这个队列中的对象称为“同事”。查看 sched()
方法的源码可以看出,所有的任务(task)都放到了 Timer 类维护的task 队列中. - 同事之间的通信都是通过 Timer来协调完成的,所以,Timer 承担了中介者的角色,而 task 队列内的任务就是具体同事对象。
以上是关于中介者模式mediator---JDK源码中的体现的主要内容,如果未能解决你的问题,请参考以下文章