跳到主要内容

外观模式

  • 外观模式(Facade Pattern)又称为门面模式,结构型设计模式,通过引入一个外观角色来简化客户端和子系统之间的交互,为复杂的子系统调度提供一个统一的入口,降低子系统和客户端的耦合度
  • 外观模式没有封装子系统的类,只是提供了简单的接口,并不限制客户端只用子系统类,因此可以在系统易用性和通用性之间自由选择
  • 外观模式注重的是简化接口,更多的是从架构的层次去看待整个系统,而非单个类的层次

结构

  • 外观模式没有一个一般化的类图描述,通常使用以下示意图来表示外观模式
    UML
    外观模式包括两个角色:
    • Facade(外观角色):在客户端可以可以调用它的方法,在外观角色中可以知道相关的(一个或多个)子系统的功能和责任,在正常情况下,它将从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理
    • SubSystem(子系统角色)
      在系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合。
      它实现子系统的功能,每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观角色传过来的请求。
      子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已

实现

  • 外观模式主要目的在于降低系统的复杂程度,在面向对象软件系统中,类之间的耦合度过大时,维护和修改都缺乏灵活性,一个类的改动会导致多个类发生变化。
    引入外观模式后,可以方便的新增或者移除子系统,客户类无需进行修改(或只需要少量修改),只需要在外观类中增加或移除对子系统的引用即可,从这一点上,外观模式一定程度上并不符合开闭原则,因为增加子系统需要对原有系统进行修改
  • 外观模式所指的子系统是一个广义的概念,可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统

代码示例

// 子系统  
class SubSystemA {
public void MethodA() {
//业务实现代码
}
}

class SubSystemB {
public void MethodB() {
//业务实现代码
}
}

class SubSystemC {
public void MethodC() {
//业务实现代码
}
}

// 外观
class Facade {
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();

public void Method() {
obj1.MethodA();
obj2.MethodB();
obj3.MethodC();
}
}

// 客户端
class Program {
public static void Main(string[] args) {
Facade facade = new Facade();
facade.Method();
}
}

优点

  1. 对客户端屏蔽子系统组件,减少客户端所需处理的对象数量,并使子系统使用更加容易,通过引入外观模式,简化客户端代码,减少关联对象
  2. 实现子系统和客户端之间的松耦合关系,使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可
  3. 一个子系统的修改对其他子系统没有影响,子系统内部变化也不会影响外观对象

缺点

  1. 不能很好的限制客户端直接使用子系统类,如果对客户端访问子系统类做太多限制则减少了可变性和灵活性
  2. 设计不当时,增加新的子系统可能需要修改外观类的代码,违背开闭原则

适用场景

  1. 当要为访问的一系列复杂的子系统提供一个简单入口时
  2. 客户端程序与多个子系统之间存在很大依赖性。引入外观系统可以将子系统和客户端解耦,提高子系统的独立性和可移植性
  3. 在结构化层次中,可以使用外观模式定义系统每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度