设计模式 - 外观模式

70 阅读3分钟

本文已参加【新人创作礼】活动,一起开启掘金创作之路。

在家吃饭和下馆子

自己在家吃饭,需要去菜市场买菜、使用厨房烹饪、吃完饭需要刷碗等。如果下馆子,只需要和服务员说吃什么,其他的就不用自己去做了。这里服务员的作用是顾客与做饭的各个步骤直接的中间人(外观),放到软件设计中,可以抽象为外观模式。

概念

外观模式(Facade Pattern):外部与一个子系统的通信通过一个统一的外观角色进行,为子系统中的一组接口提供一个一致的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

角色

  • Facade(外观角色):在客户端可以调用这个角色的方法,外观角色内部调用子系统角色
  • SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色。每个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能。每个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求。子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。

image.png

image.png

实例代码

class Facade {
    private SubSystem1 obj1 = new SubSystem1(); 
    private SubSystem2 obj2 = new SubSystem2();
    private SubSystem3 obj3 = new SubSystem3();

    public void method() {
        obj1.method();
        obj2.method();
        obj3.method();
    }
}

抽象外观类

在标准的外观模式结构图中,如果需要增加、删除或更换与外观类交互的子系统类,必须修改外观类或客户端的源代码,这将违背开闭原则。抽象外观类值客户端可以针对抽象外观类进行编程,对于新的业务需求,不需要修改原有外观类,而对应增加一个新的具体外观类。

image.png

问题记录

  • 外观模式如何体现迪米特法则? 迪米特法则(Law of Demeter,LoD):一个软件实体应当尽可能少地与其他实体发生相互作用。外观模式中,客户端只调用外观类,没有和子系统类进行交互。

总结

模式使用补充

  • 在很多情况下为了节约系统资源,系统中只需要一个外观类的实例。即外观类可以是一个单例类。
  • 外观类不应该为子系统增加新行为。

优点

  • 对客户端屏蔽了子系统,使得客户端代码更简洁
  • 实现子系统与客户端之间的松耦合

缺点

  • 设计不当,可能导致增加子系统会修改外观类的代码,违背开闭原则

参考资料

[1] 刘伟. 设计模式的艺术[M]. 清华大学出版社, 2020.