外观模式

2019-01-22 17:23:57 浏览数 (2)

外观模式遵守的面向对象的原则之一:迪米特法则。

外观模式也叫门面模式。

迪米特法则(最少知道法则)

一个软件实体应当尽可能少的与其他实体直接发生相互作用(耦合)。

核心思想

为子系统提供统一的入口封装子系统的复杂性,便于客户端调用。在一个由多个模块组成的系统中,模块与模块之间就可以通过提供外观模式来进行数据的交互,每个模块只需要暴漏出其他模块感兴趣的数据,这样就达到了各个模块之间数据的隔离。(这就很满足封装的特性:只暴露该暴漏的,其他的就隐藏起来)

在我们生活中其实也处处体现了这种思想。比如:手机运行需要主板、电池、声卡等,但我们在玩手机时只需要对屏幕操作就行了。这就是手机厂商为我们提供的统一的入口,把具体执行流程的复杂性封装了起来。我们只需要和这个统一入口打交道。

角色

  • Facade: 外观角色
  • SubSystem:子系统角色

UML 图

代码示例

子系统角色

代码语言:javascript复制
  public class SystemA {
  
      public void operatorA() {
          System.out.println("operatorA finish");
      }
  }
  
  public class SystemB {
  
      public void operatorB() {
          System.out.println("operatorB finish");
      }
  }
  
  public class SystemC {
  
      public void operatorC() {
          System.out.println("operatorC finish");
      }
  }

外观角色

代码语言:javascript复制
  public class OperatorFacade {
      public void wrapOperator(){
          SystemA a = new SystemA();
          a.operatorA();
          SystemB b = new SystemB();
          b.operatorB();
          SystemC c = new SystemC();
          c.operatorC();
      }
  }

测试类

假设我们在开发一个产品,开发某个功能需要用到 SystemA、SystemB、SystemC 三个子系统的操作才可以完成。

代码语言:javascript复制
  public class Client {
      public static void main(String[] args) {
          // 没有使用外观模式完成这个功能
          SystemA a = new SystemA();
          a.operatorA();
          SystemB b = new SystemB();
          b.operatorB();
          SystemC c = new SystemC();
          c.operatorC();
          
          // 使用外观模式完成这个功能
          new OperatorFacade().operator();    
          
      }
  }

很明显在没有使用外观模式时,我们完成一个功能需要和多个子系统直接耦合在一起,而且调用关系复杂。

开发中常见的场景

  • commons 提供的 DBUtils 类,把数据库连接、驱动加载、增删改查等都封装起来,提供一个统一的接口供我们使用,我们在写代码时只需要调接口中提供的方法就可以了。
  • tomcat 中使用了大量的外观模式(比如:HttpRequestFacade),不过它的巧妙之处在于只将别的模块感兴趣的数据封装起来,通过外观模式对其他模块提供。

优点

  • 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
  • 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。

缺点

  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了"开闭原则"。

总结

解耦客户端和子系统之间的关系,更好的封装。方便模块与模块之间的数据交互。

参考链接:https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/facade.html

0 人点赞