设计模式-中介者模式

中介者模式(MediatorPattern) : 定义了一个对象来封装一系列对象的交互. 各个对象之间不需要显式的互相引用, 而是都引用同一个中介者, 用户可以独立的改变它们之间的交互.

设计模式-概述

结构

中介者模式有4中角色:

  1. 抽象中介者(Mediator): 定义了一个接口用来各同事间通信.
  2. 具体中介者(ConcreteMediator): 具体实现了各个同事间的通信.
  3. 抽象同事类(Colleague): 定义各个同事类公有的方法, 维持了一个抽象中介者的引用, 以便子类使用.
  4. 具体同事类(ConcreteColleague): 每一个同事类对象在需要与其他同事类通信时, 需要先通过中介者完成与其他同事类的通信.

mediator-1.png

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
@@startuml mediator-1
!include common.cuml

Class(Mediator,"Mediator") <<abstract>> {
}

Class(ConcreteMediator,"具体中介者") {
}

Class(Colleague,"抽象同事类") <<abstract>> {
}

Class(ConcreteColleagueA,"具体同事类A") {
}

Class(ConcreteColleagueB,"具体同事类B") {
}

Mediator <-left- Colleague : mediator
Colleague <|-- ConcreteColleagueA
Colleague <|-- ConcreteColleagueB
ConcreteMediator --> ConcreteColleagueA
ConcreteMediator --> ConcreteColleagueB
ConcreteMediator -up-|> Mediator

@@enduml

代码实现

实现一个同事A触发某方法, 通过中介者, 群发消息的功能

  1. concreteColleagueA, concreteColleagueB 为两个同事
  2. 通过concreteColleagueA的method2(), 触发所有通过同一个中介者的同事的method1()方法.
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.yuda.desigmode.main6;

import java.util.ArrayList;
import java.util.List;

/**
* @author canyu
* @create_date 2020/12/9 20:49
*/
public class Main {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
Colleague concreteColleagueA = new ConcreteColleagueA(mediator);
Colleague concreteColleagueB = new ConcreteColleagueB(mediator);
mediator.register(concreteColleagueA);
mediator.register(concreteColleagueB);
System.out.println("触发concreteColleagueA的method2");
concreteColleagueA.method2();
}
}

abstract class Colleague {
protected Mediator mediator;

public Colleague(Mediator mediator) {
this.mediator = mediator;
}

public abstract void method1();

public void method2() {
mediator.operation();
}
}

abstract class Mediator {
protected List<Colleague> colleagueList = new ArrayList<>();

public void register(Colleague colleague) {
colleagueList.add(colleague);
}

public abstract void operation();
}

class ConcreteMediator extends Mediator {

@Override
public void operation() {
// 全部触发
for (Colleague colleague : colleagueList) {
colleague.method1();
}
}
}

class ConcreteColleagueB extends Colleague {

public ConcreteColleagueB(Mediator mediator) {
super(mediator);
}

@Override
public void method1() {
System.out.println("ConcreteColleagueB.method1");
}
}

class ConcreteColleagueA extends Colleague {

public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}

@Override
public void method1() {
System.out.println("ConcreteColleagueA.method1");
}
}

使用场景

中介者模式简化了对象之间的交互, 通过中介者和同事的一对多代替了同事之间的多对多的方式, 实现了同事之间的解耦合, 缺点是中介者的实现方式可能会很复杂.

  1. 系统中有多个对象, 对象间有复杂的引用关系.
  2. 一个对象会与多个对象通信, 且关系复杂.
  3. 想要把通信的行为封装起来, 同事类中无需维护通信行为时.

具体应用

  1. MVC架构中控制器: Controller 作为一种中介者, 它负责控制视图对象View和模型对象Model之间的交互. 如在Struts中, Action就可以作为JSP页面与业务对象之间的中介者.
  2. JDK中的Timer类的schedule()方法, 都调用了私有的sched()方法, 所有任务都加入队列, 队列中可以看做同事, 同事间通信都依赖与Timer, Timer就是中介者.