概述
外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
外观(Facade)模式又叫门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节
,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
结构
示例
下面是一些核心 Java 程序库中的外观示例:
- javax.faces.context.FacesContext 在底层使用了 LifeCycle、 ViewHandler 和 NavigationHandler 这几个类, 但绝大多数客户端不知道。
- javax.faces.context.ExternalContext 在内部使用了 ServletContext、 HttpSession、 HttpServletRequest、 HttpServletResponse 和其他一些类。
识别方法: 外观可以通过使用简单接口, 但将绝大部分工作委派给其他类的类来识别。 通常情况下, 外观管理着其所使用的对象的完整生命周期
伪代码实现
外观 (Facade)
外观 (Facade) 提供了一种访问特定子系统功能的便捷方式, 其了解如何重定向客户端请求, 知晓如何操作一切活动部件。
interface Facade {
public void method();
}
附加外观 (Additional Facade)
创建附加外观 (Additional Facade) 类可以避免多种不相关的功能污染单一外观, 使其变成又一个复杂结构。 客户端和其他外观都可使用附加外观。
//外观角色
class FacadeImpl1 implements Facede
{
private SubSystem01 obj1=new SubSystem01();
private SubSystem02 obj2=new SubSystem02();
private SubSystem03 obj3=new SubSystem03();
public void method()
{
obj1.method1();
obj2.method2();
obj3.method3();
}
}
//外观角色
class FacadeImpl1 implements Facede
{
private SubSystem02 obj2=new SubSystem02();
private SubSystem03 obj3=new SubSystem03();
private SubSystem04 obj4=new SubSystem04();
public void method()
{
obj2.method2();
obj3.method3();
obj4.method4();
}
}
复杂子系统 (Complex Subsystem)
复杂子系统 (Complex Subsystem) 由数十个不同对象构成。 如果要用这些对象完成有意义的工作, 你必须深入了解子系统的实现细节, 比如按照正确顺序初始化对象和为其提供正确格式的数据。
子系统类不会意识到外观的存在, 它们在系统内运作并且相互之间可直接进行交互。
//子系统角色
class SubSystem01
{
public void method1()
{
System.out.println("子系统01的method1()被调用!");
}
}
//子系统角色
class SubSystem02
{
public void method2()
{
System.out.println("子系统02的method2()被调用!");
}
}
//子系统角色
class SubSystem03
{
public void method3()
{
System.out.println("子系统03的method3()被调用!");
}
}
//子系统角色
class SubSystem04
{
public void method4()
{
System.out.println("子系统04的method4()被调用!");
}
客户端 (Client)
客户端 (Client) 使用外观代替对子系统对象的直接调用。
public class FacadePattern
{
public static void main(String[] args)
{
Facade f=new FacadeImpl1();
f.method();
f=new FacadeImpl2();
f.method();
}
}
应用场景
如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。
子系统通常会随着时间的推进变得越来越复杂。 即便是应用了设计模式, 通常你也会创建更多的类。
尽管在多种情形中子系统可能是更灵活或易于复用的, 但其所需的配置和样板代码数量将会增长得更快。
为了解决这个问题, 外观将会提供指向子系统中最常用功能的快捷方式, 能够满足客户端的大部分需求。
如果需要将子系统组织为多层结构, 可以使用外观。
创建外观来定义子系统中各层次的入口。
你可以要求子系统仅使用外观来进行交互, 以减少子系统之间的耦合。
实现步骤
首先,考虑能否在现有子系统的基础上提供一个更简单的接口
。
如果该接口能让客户端代码独立于众多子系统类, 那么你的方向就是正确的。
其次,在一个新的外观类中声明并实现该接口
。
外观应将客户端代码的调用重定向到子系统中的相应对象处。
如果客户端代码没有对子系统进行初始化, 也没有对其后续生命周期进行管理, 那么外观必须完成此类工作。
之后,为了充分发挥这一模式的优势, 你必须确保所有客户端代码仅通过外观来与子系统进行交互
。
此后客户端代码将不会受到任何由子系统代码修改而造成的影响, 比如子系统升级后, 你只需修改外观中的代码即可。
最后,如果外观变得过于臃肿, 你可以考虑将其部分行为抽取为一个新的专用外观类。
优缺点
优点:
- 简化了调用过程,无需了解深入子系统,防止带来风险
- 减少系统依赖、松散耦合
- 更好的划分访问层次
- 符合迪米特法则,即最少知道原则
缺点:
- 增加子系统、扩展子系统行为容易引入风险
- 不符合开闭原则