中介者模式

中介者模式

一、定义

摘自百度百科:用一个中介对象来封装一系列对象的交互,从而把一批原来可能是交互关系复杂的对象转换成一组松散耦合的中间对象,以有利于维护和修改。

点击查看源码


二、角色分类

抽象中介者(Mediator)

声明了同时对象到中介者对象的接口

具体中介者(Concrete Mediator)

其为具体中介者的子类,从具体的同事对象接收消息,向具体同事发出命令

抽象同事角色(Colleague)

声明了中介者对象接口,它只知道中介者对象,而不知道其他同事对象

具体同事角色(Concrete Colleague)

其为抽象同事的子类,每个具体同事类都知道自己在小范围内的行为,而不知道其在大范围内的目的

客户角色(Client)

具体调用方法的角色


三、实现方式

UML图

未命名文件 (1)

具体实现

抽象中介者(Mediator)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Mediator {

protected ConcreteColleagueA colleagueA;
protected ConcreteColleagueB colleagueB;

public void setColleagueA(ConcreteColleagueA colleague) {
this.colleagueA = colleague;
}

public void setColleagueB(ConcreteColleagueB colleague) {
this.colleagueB = colleague;
}

public abstract void transferA();

public abstract void transferB();

}

具体中介者(Concrete Mediator)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ConcreteMediator extends Mediator {
/**
* 由具体同事A,向具体同事B发出指令
*/
@Override
public void transferA() {
this.colleagueB.selfMethodB();
}

/**
* 由具体同事B,向具体同事A发出指令
*/
@Override
public void transferB() {
this.colleagueA.selfMethodA();
}
}

抽象同事类(Colleague)

1
2
3
4
5
6
7
8
9
public abstract class Colleague {

protected Mediator mediator;

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

}

具体同事类(Concrete Colleague)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConcreteColleagueA extends Colleague {
public ConcreteColleagueA(Mediator mediator) {
super(mediator);
this.mediator.setColleagueA(this);
}

/**
* 自有方法
*/
public void selfMethodA() {
System.out.println("同事A收到中介协作通知");
}

/**
* 依赖方法
*/
public void depMethodA() {
System.out.println(this.getClass().getSimpleName() + " depMethodA通知中介者进行转发协作");
// 中介者进行转发协作
this.mediator.transferA();
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConcreteColleagueB extends Colleague {
public ConcreteColleagueB(Mediator mediator) {
super(mediator);
this.mediator.setColleagueB(this);
}

/**
* 自有方法
*/
public void selfMethodB() {
System.out.println("同事B收到中介协作通知");
}

/**
* 依赖方法
*/
public void depMethodB() {
System.out.println(this.getClass().getSimpleName() + " depMethodB通知中介者进行转发协作");
// 中介者进行转发协作
this.mediator.transferB();
}

}

客户角色(Client)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Client {

public static void main(String[] args) {
// 创建抽象中介者
Mediator mediator = new ConcreteMediator();
// 具体同事类
ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
// 中介者进行转发协作,A转发给B
colleagueA.depMethodA();
System.out.println("-------------------------");
// 中介者进行转发协作,B转发给A
colleagueB.depMethodB();
}

}

运行结果

1
2
3
4
5
ConcreteColleagueA depMethodA通知中介者进行转发协作
同事B收到中介协作通知
-------------------------
ConcreteColleagueB depMethodB通知中介者进行转发协作
同事A收到中介协作通知

四、应用场景

以下部分内容摘自菜鸟教程

意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

主要解决:对于一些固定文法构建一个解释句子的解释器。

何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

如何解决:构建语法树,定义终结符与非终结符。

关键代码:构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。

应用实例:编译器、运算表达式计算。

使用场景:

  1. 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
  2. 一些重复出现的问题可以用一种简单的语言来进行表达。
  3. 一个简单语法需要解释的场景。

注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。


五、优缺点

优点

  1. 可扩展性比较好,灵活。
  2. 增加了新的解释表达式的方式。
  3. 易于实现简单文法。

缺点

  1. 可利用场景比较少。
  2. 对于复杂的文法比较难维护。
  3. 解释器模式会引起类膨胀。
  4. 解释器模式采用递归调用方法。