中介者模式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("我很好!");
    }

}

在这里插入图片描述

另 优化:

在实际开发中,通常采用以下两种方法来简化中介者模式,使开发变得更简单。

  1. 不定义中介者接口,把具体中介者对象实现成为单例。
  2. 同事对象不持有中介者,而是在需要的时直接获取中介者对象并调用。

如图所示是简化中介者模式的结构图:

在这里插入图片描述

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源码中的体现的主要内容,如果未能解决你的问题,请参考以下文章

设计模式(十八)—— 中介者模式

设计模式之中介者模式(行为型)

设计模式之中介者模式(行为型)

设计模式中介者模式

代理模式-1(静态代理)

代理模式-1(静态代理)