什么是门面模式(Facade)
概念
门面模式,又叫做外观模式,属于结构型模式。我个人比较喜欢叫门面模式,因为这个模式是为了隐藏系统内部的复杂性,向外部提供一个统一的接口,使得外部访问该系统更加方便、更加简单。
门面模式是迪米特法则的代表,它关心对象和对象之间的组合关系,它主要是想几个对象之间的复杂操作都封装在一个高层次的类中,外部调用无需关心它内部的逻辑,只需要调用自己想要的功能即可。
我们在日常的开发中也会用到门面模式,用过Spring做开发的小伙伴一定知道MVC的层次划分,其中Controller层和Service层都用到了门面模式,它们都封闭了内部的复杂性,为外部提供一个方便调用的接口。我再举一个通俗的例子,想我们去洗衣服,如果是我们自己洗的话,需要先加洗衣液来洗,拧干,洗完过清水,再拧干,再过清水,最后需要拧的更干,这个步骤非常地多;如果使用洗衣机的话,我们就只需要把衣服倒到洗衣机,洗衣服的步骤就由洗衣机来做了。这里的洗衣机就封闭了洗衣服的过程,我们只需要把衣服丢到洗衣机即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-srQRQ6Do-1633180909855)(https://gitee.com/xuxiaojian1999/image-bed/raw/master/img/%E6%BB%91%E7%A8%BD%E8%84%B8%E6%B4%97%E8%A1%A3%E6%9C%BA.gif)]
优点
门面模式满足迪米特法则,它的大部分优点都是跟迪米特法则相似的。
- 降低了子系统和调用者间的耦合度,调用者只需要调用这个门面即可,不需要去关心底下有多少个子系统。
- 使得调用更加的方便。
- 减少了系统的相互依赖,增加了系统的灵活性。只要提供门面不变,无论系统内部的逻辑如何改变都可以。
缺点
不符合开放封闭原则。每次有新的改动都需要去修改门面,想要继承重写,组合都很难完成。
原则
“+”代表遵守,“-”代表不遵守或者不相关
| 原则 | 开放封闭 | 单一职责 | 迪米特 | 里氏替换 | 依赖倒置 | 接口隔离 | 合成复用 |
|---|---|---|---|---|---|---|---|
| - | - | + | - | - | - | + | |
适用场景
- 模块或子系统中的组件太多了,调用过程十分麻烦。这种情况就需要使用门面模式来提供一个更加方便调用的接口了,不然这个模块使用起来非常复杂。
- 模块或子系统内部相对独立。这种情况,我们提供好暗箱操作,减少调用者的使用难度。
- 预防低水平人员带来的风险。就是让这个模块使用起来更加简单,让每个人都能使用。
如何实现
想要实现门面模式(外观模式),需要以下两样东西:
- 门面(外观)类:负责处理调用子系统的逻辑。
- 子系统类:提供系统的部分功能。
上类图

上代码
这里实现洗衣机的例子。
子系统类:SubSystemA/B/C
/**
* 子系统类
* 模拟洗衣机的组件:滚筒
* Created on 2021/6/3.
*
* @author xuxiaobai
*/
public class SubSystemA {
/**
* 滚动
*/
public void operate(){
System.out.println("滚起来。。。。");
}
}
——————————————————————————
/**
* 子系统类
* 模拟洗衣机的组件:排水管
* Created on 2021/6/3.
*
* @author xuxiaobai
*/
public class SubSystemB {
/**
* 排水
*/
public void operate(){
System.out.println("排水中。。。。");
}
}
———————————————————————————
/**
* 子系统类
* 模拟洗衣机的组件:加水管
* Created on 2021/6/3.
*
* @author xuxiaobai
*/
public class SubSystemC {
/**
* 加水
*/
public void operate(){
System.out.println("加水。。。。");
}
}
门面类:Facade
/**
* 门面类
* 模拟洗衣机
* Created on 2021/6/3.
*
* @author xuxiaobai
*/
public class Facade {
private SubSystemA subSystemA=new SubSystemA();
private SubSystemB subSystemB=new SubSystemB();
private SubSystemC subSystemC=new SubSystemC();
/**
* 洗衣服
*/
public void operate(){
System.out.println("开始洗衣服");
subSystemC.operate();
subSystemA.operate();
subSystemB.operate();
System.out.println("第一遍洗完了");
subSystemC.operate();
subSystemA.operate();
subSystemB.operate();
System.out.println("第二遍洗完了");
subSystemC.operate();
subSystemA.operate();
subSystemB.operate();
System.out.println("衣服洗完了,滴滴滴");
}
}
测试类:FacadeTest
/**
* Created on 2021/6/3.
*
* @author xuxiaobai
*/
public class FacadeTest {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operate();
/**
* 开始洗衣服
* 加水。。。。
* 滚起来。。。。
* 排水中。。。。
* 第一遍洗完了
* 加水。。。。
* 滚起来。。。。
* 排水中。。。。
* 第二遍洗完了
* 加水。。。。
* 滚起来。。。。
* 排水中。。。。
* 衣服洗完了,滴滴滴
*/
}
}

Facade类内部封装了洗衣机的操作过程,只需要调用operate方法即可完成洗衣操作。
总结
门面模式不符合开放封闭原则,但这也是我们最常使用的设计模式,使用起来不要太方便了,也不会太难,作为Java开发人员,这个设计模式的思想应该是与生俱来的了,唯一需要注意的是每个门面类封装的操作都是在同一个层次的,像一个洗衣机,可以再封装开关电源的方法,但不能封装关总闸的方法。
门面模式(Facade)是一种结构型设计模式,用于简化系统内部复杂性,提供一个统一的外部接口。它遵循迪米特法则,降低子系统与调用者间的耦合,使调用更方便。在Spring MVC中,Controller和Service层即体现了这一模式。洗衣机例子展示了门面如何封装操作流程。虽然不符合开放封闭原则,但因其便利性而常用。实现门面模式需创建门面类处理调用逻辑,子系统类提供功能。在子系统过多或需要简化调用时适用。

被折叠的 条评论
为什么被折叠?



