行为型模式:中介者模式

LieBrother公众号原文
行为型模式:中介者模式

景

十一大行为型模式之二:中介者模式。

简介

姓名 :中介者模式

英文名 :Mediator Pattern

价值观 :让你体验中介是无所不能的存在

个人介绍

Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly,and it lets you vary their interaction independently.
用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
(来自《设计模式之禅》)

你要的故事

看了这小伙子的名字,大家会很直观的想到那些拿了我们半个月租的租房中介同学。在这不讲讲房租中介同学,以后可没机会了。大家现在找房子,不管是买还是租,一登录什么安居客、58同城,是不是有 80% 是经纪人房源,说 80% 还是比较保守的,经历了 4 次找房,发现个人房源越来越少。每个网站都有个选项:经纪人房源。如下图:

房源

(图片截自:安居客网站)

经纪人就扮演着中介的角色,和本文要讲的中介者模式完全吻合。我们在找房子的时候,经纪人扮演什么角色呢?我们通过个人房源和经纪人房源的租房案例来简单描述经纪人的角色。

个人房源

我们通过个人房源找房子的方式是这样的:在网上找个人房源的房东,然后挨个联系,和房东约定好时间去看房,我们跟房东的关系是一对多的关系。小明就在网上看了个人房源,联系了房东,分别去看了农民房和小区房,用代码表示如下。

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
public class PersonalTest {

public static void main(String[] args) {
Tenant xiaoMing = new Tenant("小明");
xiaoMing.lookAtHouse();
}

}

class Tenant {
private String name;
private XiaoQuFangLandlord xiaoQuFangLandlord2 = new XiaoQuFangLandlord();
private NongMinFangLandlord nongMinFangLandlord2 = new NongMinFangLandlord();

public Tenant(String name) {
this.name = name;
}

public void lookAtHouse() {
System.out.println(this.name +"想看农民房");
nongMinFangLandlord2.supply();
System.out.println(this.name + "想看小区房");
xiaoQuFangLandlord2.supply();
}

}

/**
* 房东
*/
abstract class Landlord {
// 提供房子
public abstract void supply();
}

class XiaoQuFangLandlord extends Landlord {

@Override
public void supply() {
System.out.println("小区房的房东提供一间小区房");
}
}

class NongMinFangLandlord extends Landlord {

@Override
public void supply() {
System.out.println("农民房的房东提供一间小区房");
}
}

打印结果如下:
小明想看农民房
农民房的房东提供一间小区房
小明想看小区房
小区房的房东提供一间小区房

小明分别联系小区房的房东和农民房的房东,然后依次去看了农民房和小区房。这样子有个弊端就是小明和房东是强关联的关系,其实小明只是去看一下房,看完不想租就和房东没啥关系了。这个时候经纪人就派上用场了,经纪人的主要任务就是把房子租出去,所以他和房东应该是强关系,直到把房子成功租出去了,才和房东脱离关系,而小明也不用去挨个找房东看房子了,这个职责转给经纪人,小明只需要联系一个人,那就是经纪人,跟他说我要看小区房和农民房,经纪人就带他去看。下面就介绍经纪人房源的方式,也就是本文要讲的中介者模式。

经纪人房源

用经纪人房源找房子,小明就省心很多了,小明就只联系了一个经纪人,跟他描述了自己要的房源:小区房和农民房都可以,经纪人里面和他约定了一个下午的时间,把小明所有想看的房让他看完,最终小明决定租了一间房。看代码。

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
public class MediatorTest {

public static void main(String[] args) {
System.out.println("小明想要看小区房和农民房");
Tenant2 xiaoMing = new Tenant2("小明", Arrays.asList("XiaoQuFang", "NongMinFang"));
xiaoMing.lookAtHouse();
}


}

/**
* 租客
*/
class Tenant2 {
private String name;
private List<String> wantTypes;

private RentingMediator rentingMediator = new RentingMediator();

public Tenant2(String name, List<String> wantTypes) {
this.name = name;
this.wantTypes = wantTypes;
}

public void lookAtHouse() {
rentingMediator.supplyHouse(wantTypes);
}

}

/**
* 中介抽象类
*/
abstract class Mediator {
// 看房
public abstract void supplyHouse(List<String> types);
}

/**
* 租房中介
*/
class RentingMediator extends Mediator {

private XiaoQuFangLandlord xiaoQuFangLandlord;
private NongMinFangLandlord nongMinFangLandlord;

public RentingMediator() {
xiaoQuFangLandlord = new XiaoQuFangLandlord();
nongMinFangLandlord = new NongMinFangLandlord();
}

@Override
public void supplyHouse(List<String> types) {
System.out.println("经纪人提供了如下房源");
if (types.contains("XiaoQuFang")) {
xiaoQuFangLandlord.supply();
}
if (types.contains("NongMinFang")) {
nongMinFangLandlord.supply();
}
}
}

打印结果:
小明想要看小区房和农民房
经纪人提供了如下房源
小区房的房东提供一间小区房
农民房的房东提供一间小区房

在代码中,我们可以看到小明和经纪人是一对一关系,经纪人和房东是一对多关系。小明找房经历也轻松多了,只花了一下午就把房子都看了并看中了。这也是中介者模式的优点,减少了不必要的依赖,降低了类间的耦合

代码:
Mediator Pattern

总结

中介者模式通过在互相依赖的对象中间加了一层,让原本强依赖的对象变成弱依赖。在软件编程中,有一个中介者模式的典型的例子,就是 MVC 框架,也称三层架构,通过 Controller (控制层) 将 Model (业务逻辑层) 和 View (视图层) 的依赖给分离开,协调 Model 和 View 中的数据和界面交互工作。看看你工作中的代码,想想看有没有哪些对象之间的关系特紧密特混乱,考虑是不是可以通过中介者模式来把依赖关系剥离,让代码更清晰。

参考资料:《大话设计模式》、《设计模式之禅》

推荐阅读:

行为型模式:模板方法

公众号之设计模式系列文章

希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。