设计模式笔记10:外观模式(Facade Pattern)
一、外观模式的内容
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
医院的例子
用一个例子进行说明,如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。
首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴款,才能到化验部门做化验。化验后,再回到门诊室。
解决这种不便的方法便是引进门面模式。可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。这个接待员就是门面模式的体现,病人只接触接待员,由接待员负责与医院的各个部门打交道。
二、外观模式的结构
在这个对象图中,出现了两个角色:
门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
三、外观模式分析
- 根据“单一职责原则”,在软件中将一个系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统的访问提供了一个简单而单一的入口。
- 外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度
- 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。
- 外观模式的目的在于降低系统的复杂程度。
- 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能。
- 适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而外观模式将一群对象“包装”起来以简化其接口。
四、外观模式示例代码
子系统
public class Fan { public void on() { System.out.println("风扇打开!"); } public void off() { System.out.println("风扇关闭!"); } }
public class Light { private String position; public Light(String position) { this.position=position; } public void on() { System.out.println(this.position + "灯打开!"); } public void off() { System.out.println(this.position + "灯关闭!"); } }
public class Television { public void on() { System.out.println("电视机打开!"); } public void off() { System.out.println("电视机关闭!"); } }
public class AirConditioner { public void on() { System.out.println("空调打开!"); } public void off() { System.out.println("空调关闭!"); } }外观
public class GeneralSwitchFacade { private Light lights[]=new Light[4]; private Fan fan; private AirConditioner ac; private Television tv; public GeneralSwitchFacade() { lights[0]=new Light("左前"); lights[1]=new Light("右前"); lights[2]=new Light("左后"); lights[3]=new Light("右后"); fan=new Fan(); ac=new AirConditioner(); tv=new Television(); } public void on() { lights[0].on(); lights[1].on(); lights[2].on(); lights[3].on(); fan.on(); ac.on(); tv.on(); } public void off() { lights[0].off(); lights[1].off(); lights[2].off(); lights[3].off(); fan.off(); ac.off(); tv.off(); } }测试
public class Client { public static void main(String args[]) { GeneralSwitchFacade gsf=new GeneralSwitchFacade(); gsf.on(); System.out.println("-----------------------"); gsf.off(); }
五、模式扩展
- 一个系统有多个外观类
- 不要试图通过外观类为子系统增加新行为
- 外观模式与迪米特法则
- 抽象外观类的引入
六、外观模式优缺点
外观模式的优点
- 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
- 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
- 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
- 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
外观模式的缺点
- 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
- 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
七、模式适用环境
在以下情况下可以使用外观模式:- 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
- 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
八、外观模式应用
(1) 外观模式应用于JDBC数据库操作public class JDBCFacade { private Connection conn=null; private Statement statement=null; public void open(String driver,String jdbcUrl,String userName,String userPwd) { ...... } public int executeUpdate(String sql) { ...... } public ResultSet executeQuery(String sql) { ...... } public void close() { ...... } }(2) Session外观模式是外观模式在Java EE框架中的应用。
Facade (recognizeable by behavioral methods which internally uses instances of different independent abstract/interface types)
-
javax.faces.context.FacesContext
, it internally uses among others the abstract/interface typesLifeCycle
,ViewHandler
,NavigationHandler
and many more without that the enduser has to worry about it (which are however overrideable by injection). -
javax.faces.context.ExternalContext
, which internally usesServletContext
,HttpSession
,HttpServletRequest
,HttpServletResponse
, etc.
九、参考资料
- http://blog.csdn.net/rocket5725/article/details/4315155
- http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns
- 《设计模式》刘伟主编清华大学出版社
- 《Head First 设计模式》