设计模式(16)——外观模式

本文介绍外观模式的概念和应用。

基本思想和原则

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供了一个高层次的接口,使得子系统更易于使用。

动机

当某个子系统的业务逻辑和内部关系比较复杂时,可以考虑使用外观模式做一层封装,对外屏蔽这个子系统,高层模块不直接和子系统交互,而是和外观对象交互,外观对象在内部将真正的业务处理过程委托给子系统来处理。

实现

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
public class Consulate {
public void getTravelVisa() {
System.out.println("Consulate get travel visa.");
}
}

public class AirlineCompany {
public void bookingAirlineTickets() {
System.out.println("AirlineCompany booking airline tickets.");
}
}

public class Hotel {
public void bookingRoom() {
System.out.println("Hotel booking room.");
}
}

public class Context {
private Consulate consulate = new Consulate();
private AirlineCompany airlineCompany = new AirlineCompany();
private Hotel hotel = new Hotel();

public void travelAbroad() {
System.out.println("------ travel abroad start ------");
this.consulate.getTravelVisa();
this.airlineCompany.bookingAirlineTickets();
this.hotel.bookingRoom();
System.out.println("------ travel abroad end ------");
}
}

public class TravelAgency {
private Context context = new Context();

public void travelAbroad() {
this.context.travelAbroad();
}
}

public class Test {
public static void main(String[] args) {
TravelAgency travelAgency = new TravelAgency();
travelAgency.travelAbroad();
}
}

输出如下:

1
2
3
4
5
------ travel abroad start ------
Consulate get travel visa.
AirlineCompany booking airline tickets.
Hotel booking room.
------ travel abroad end ------

上面的代码模拟了一个人出国旅游的过程,出国旅游之前至少需要以下几个流程:签证、订机票、订酒店房间。如果让用户(高层模块)直接去处理这几件事情(一个子系统)是很麻烦的事情,于是旅行社这种机构出现了,只要用户提交了申请材料,它就能帮助用户办完这一切事物,旅行社相当于出国旅行这一系列操作的一个“外观”,用户只需要和旅行社沟通就能搞定一切事情,不需要分别去找领事馆、航空公司和当地酒店,对用户而言原本一堆复杂的事情经过旅行社“包装”一下变得异常轻松。

优点

外观模式减少了高层模块对子系统内部的依赖性,高层模块只需要依赖外观对象,而对子系统内部是一无所知的。另外外观模式使得子系统变动的灵活性比较高,只要外观对象不变,子系统的变化就不会影响到高层模块。同时外观模式还能对子系统实施安全控制,只提供允许外部访问的功能。

缺点

外观模式的一个问题就是外观对象的责任重大,修改它的代价可能会很大。