本文已参加【新人创作礼】活动,一起开启掘金创作之路。
在家吃饭和下馆子
自己在家吃饭,需要去菜市场买菜、使用厨房烹饪、吃完饭需要刷碗等。如果下馆子,只需要和服务员说吃什么,其他的就不用自己去做了。这里服务员的作用是顾客与做饭的各个步骤直接的中间人(外观),放到软件设计中,可以抽象为外观模式。
概念
外观模式(Facade Pattern):外部与一个子系统的通信通过一个统一的外观角色进行,为子系统中的一组接口提供一个一致的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
角色
- Facade(外观角色):在客户端可以调用这个角色的方法,外观角色内部调用子系统角色
- SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色。每个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能。每个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求。子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。
实例代码
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();
}
}
抽象外观类
在标准的外观模式结构图中,如果需要增加、删除或更换与外观类交互的子系统类,必须修改外观类或客户端的源代码,这将违背开闭原则。抽象外观类值客户端可以针对抽象外观类进行编程,对于新的业务需求,不需要修改原有外观类,而对应增加一个新的具体外观类。
问题记录
- 外观模式如何体现迪米特法则? 迪米特法则(Law of Demeter,LoD):一个软件实体应当尽可能少地与其他实体发生相互作用。外观模式中,客户端只调用外观类,没有和子系统类进行交互。
总结
模式使用补充
- 在很多情况下为了节约系统资源,系统中只需要一个外观类的实例。即外观类可以是一个单例类。
- 外观类不应该为子系统增加新行为。
优点
- 对客户端屏蔽了子系统,使得客户端代码更简洁
- 实现子系统与客户端之间的松耦合
缺点
- 设计不当,可能导致增加子系统会修改外观类的代码,违背开闭原则
参考资料
[1] 刘伟. 设计模式的艺术[M]. 清华大学出版社, 2020.