为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式其实也很好理解,举个简单例子:我们去医院的话,经常要经历挂号、缴费、取药等步骤,如果有要求化验啥的,还得先去缴费,然后去化验,再回医生那边继续确诊。如果医院安排个接待员,负责帮来看病的人挂号、缴费、取药等,就方便了很多。而这个接待员即是我们要讲的外观模式。病人只需和接待员接触,不用亲自到每个部门去。
外观模式结构图

- Facade:客户端可以调用这个角色的方法。该角色知道相关子系统的功能与责任。会将客户端发来的请求委派给相应的子系统。
- SubSystem:可有一个或多个子系统。每个子系统可被客户端直接调用或Facade角色调用。子系统不知道Facade的存在,对于子系统来说,Facade只是另一个Client而已。
案例分析
来看一个很简单的案例。我们要取一个重要文件,文件锁在一个箱子中,箱子的钥匙被锁在另一个箱子中。我们自己来取的话需要先取第一个箱子里的钥匙,通过钥匙再去取第二个箱子的重要文件。在例子中,我们定义了一个帮手,我们只要跟他说要那个文件,剩下的就交给他了。
定义两个箱子,第一个箱子里放着钥匙,第二个箱子里放着重要文件。
123456789101112131415161718192021public class DrawerOne {public void open(){System.out.println("打开第一个箱子");getKey();}public void getKey(){System.out.println("得到钥匙");}}public class DrawerTwo {public void open(){System.out.println("打开第二个箱子");getFile();}public void getFile(){System.out.println("得到重要文件");}}召唤帮手来,我们只要文件,怎么拿到让帮手自己去解决:
12345678public class Facade {DrawerOne one = new DrawerOne();DrawerTwo two = new DrawerTwo();public void open(){one.open();two.open();}}这样,就可以叫帮手干活了:
1234public static void main(String[] args) {Facade drawer = new Facade();drawer.open();}看看活干得如何
1234打开第一个箱子得到钥匙打开第二个箱子得到重要文件
总结
外观模式,其实就是要做的事情步骤有点繁琐或者负责,自己不想一步一步实现,于是交给一个角色来专门打理。即为一个复杂的子系统提供一个简单的接口。这样做也提高了子系统的独立性。
优点
- 降低耦合。降低了客户端与子系统的耦合,让子系统内部模块能更容易拓展和维护。
- 简单易用。让复杂的子系统更加容易使用。客户端不需要了解子系统的内部实现。也不需要与子系统内部模块进行交互,只要跟Facade角色进行交互即可。
- 更好的划分访问层次。合理使用Facade角色,可以更好的划分访问层次。有些方法是对系统外的,有些是对系统内的,把需要暴露给外部的功能集中到门面中,这样既方便客户端使用也很好地隐藏了内部的细节。
缺点
- 不能很好的限制客户使用子系统。
- 在不引入抽象外观类的情况下,增加子系统可能需要修改外观来或客户端,违反了“开放-封闭原则”。