# 中介者模式Mediator
阅读量  loading 
 # 一、概念
# 1、定义
定义一个封装一组对象如何交互的对象
# 2、补充
通过是对象明确的相互引用来促进松散耦合,并允许独立地改变
# 3、类型
行为型
# 4、适用场景
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解
 - 交互的公共行为,如果需要改变行为则可以增加新的中介者类
 
# 5、优点
- 将一对多转化成了一对一,降低程序复杂度
 - 解决了类之间耦合
 
# 6、缺点
- 中介者过多,导致系统复杂
 
# 7、相关设计模式
- 中介者模式和观察者模式
 
有时候会使用观察者模式实现中介者模式中的角色间的通讯
# 二、应用
看这样子的业务场景,qq群中的通讯。
qq群类:
public class StudyGroup {
    public static void showMessage(User user, String message) {
        System.out.println(new Date().toInstant() + " [" + user.getName() + "]: " + message);
    }
}
 1
2
3
4
5
6
2
3
4
5
6
有一个静态方法,代表某个用户进行消息发送。
用户类:
public class User {
    private String name;
    public User(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void sendMessage(String message) {
        StudyGroup.showMessage(this, message);
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
测试类:
public class Test {
    public static void main(String[] args) {
        User jerry = new User("jerry");
        User user = new User("user");
        jerry.sendMessage("Hello, user");
        user.sendMessage("Hi, jerry");
    }
}
 1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
执行结果:
2020-06-27T09:28:02.658Z [jerry]: Hello, user
2020-06-27T09:28:02.709Z [user]: Hi, jerry
 1
2
2
类图:

# 三、源码中的应用
# Timer
java.util 包中的 Timer 的 schedule() 方法重载有很多,方法内部又调用了 sched() 方法。Timer 可以理解成中介者,而 sched() 方法中的 TimerTask 就是协调的 User 。
    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();
        }
    }
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27