Facade模式
一、定义
为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。
二、例子1
大致意思是说:使用一种比原有方式更简单的办法与系统交互。例如,我们把一个很文件的文件,放在了第二抽屉里,而第二个抽屉的钥匙放在了第一个抽屉里,我们要想取出这个文件,第一步肯定要拿到第一个抽屉的钥匙,然后打开它再拿出第二个抽屉的钥匙,最后打开第二个抽屉取出文件。
我就上面说的那个情形写一下实现代码,首先我们要实现二个子系统,呵呵,把抽屉比喻成系统,(DrawerOne、DrawerTwo):
子系统1
class DrawerOne { public void open() { System.out.println("第一个抽屉被打开了"); getKey(); } public void getKey() { System.out.println("得到第二个抽屉的钥匙"); } }
子系统2
class DrawerTwo { public void open() { System.out.println("第二个抽屉被打开了"); getFile(); } public void getFile() { System.out.println("得到这个重要文件"); } }
不使用Façade模式的情况
public class Client { public static void main(String[] args) { DrawerOne darwerOne = new DrawerOne(); DrawerTwo darwerTwo = new DrawerTwo(); darwerOne.open(); darwerTwo.open(); } }
由于没有使用Façade模式,可以看到要想得到这个文件要首先打开第一个抽屉,然后再打开第二个抽屉,在我们实际所开发的系统中,有时候客户要实现某一操作,并不需要知道实现这一操作的详细步骤,而是简单地点击某一个按钮就可以得到自己想要的结果。
使用Façade模式进行改进,建立一个FacadeDrawer类:
class DrawerFacade { DrawerOne darwerOne = new DrawerOne(); DrawerTwo darwerTwo = new DrawerTwo(); public void open() { darwerOne.open(); darwerTwo.open(); } }
修改Client类:
public class DrawerClient{ public static void main(String []args){ DrawerFacade drawer=new DrawerFacade(); drawer.open(); } }
输出结果如下:
第一个抽屉被打开了 得到第二个抽屉的钥匙 第二个抽屉被打开了 得到这个重要文件 |
正如上面所说,客户端client,它并不需要关心子系统,而是关心DrawerFacade所留下来的和外部交互的接口,而子系统在DrawerFacade的聚合。
三、例子2
A系统有A1, A2, A3等类。客户端需要调用A系统的的A1.doSomething1();A2.doSomething2();A3.doSomething3()三个方法来完成某功能。Facade模式的实现模型就是:
A1
class A1 { public void doSomething1() {} }
A2
class A2 { public void doSomething2() {} }
A3
class A3 { public void doSomething3() {} }
Facade:
public class Facade { public void doSomething() { A1 a1 = new A1(); A1 a2 = new A2(); A1 a3 = new A3(); a1.doSomething1(); a2.doSomething2(); a3.doSomething3(); } }
Client:
public class Client { public static void main(String[] args) { Facade facade = new Facade(); facade.doSomething(); } }
四、适用性
Facade模式主要适用于以下几种情况:
1. 为一个复杂子系统提供一个简单接口。
当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过facade层。
2.提高子系统的独立性
客户程序与抽象类的实现部分之间存在着很大的依赖性。引入facade 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
3.在层次化结构中,可以使用Facade模式定义系统中每一层的入口。
当你需要构建一个层次结构的子系统时,使用facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们之间的依赖关系。
4.希望使用原系统的功能,而且还希望增加一些新的功能。
五、Facade的几个要点
从客户程序的角度来看,Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Façade接口的变化。
Façade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Façade很多时候更是一种架构设计模式。
Façade设计模式并非一个集装箱,可以任意地放进任何多个对象。Façade模式中组件的内部应该是“相互耦合关系比较大的一系列组件”,而不是一个简单的功能集合。
注意区分Façade模式、Adapter模式、Bridge模式与Decorator模式。Façade模式注重简化接口,Adapter模式注重转换接口,Bridge模式注重分离接口(抽象)与其实现,Decorator模式注重稳定接口的前提下为对象扩展功能。