持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情
概念
门面模式(Facade)是一种结构型设计模式,它能将多个不同的子系统接口封装起来,并对外提供统一的高层接口,使复杂的子系统变得更易使用。
无论是“门”还是“面”,指代的都是某系统的外观部分,也就是与外界接触的临界面或接口,所以门面模式常常也被翻译为“外观模式”
实例演示
注:本文内容参考 《秒懂设计模式》一书,本文对其做了概括凝练,主要是为了自身学习使用,如果无法理解,建议查看原书。
傻瓜相机其实是一个很好的例子用于解释门面模式。
早期的相机使用起来是非常麻烦的,拍照前总是要根据场景情况进行一系列复杂的操作,如对焦、调节闪光灯、调光圈等,非专业人士面对这么一大堆的操作按钮根本无从下手,拍出来的照片质量也不高。
而对于傻瓜相机来说,用户再也不必学习那些复杂的参数调节了,只要按下快门键就可完成所有操作。
即 傻瓜相机把复杂的功能都隐藏在内部,最终只为外接提供一个简单方便的快门按键,让用户能够一键操作。 这就是门面模式的精髓。
对于门面模式在日常工作中的具体应用,我们还是举一个简单的例子来演示下。既然是门面模式,那么我们就以商铺门面来举例。
1. 亲自下厨(内部流程)
假设小明同学想要亲自下厨做饭,但因不会做菜所以请妹妹帮忙。我们将步骤简化为以下 3 步,首先小明找菜贩买菜,然后找妹妹做菜,最后亲自洗碗。
首先小明需要去找菜贩买菜,代码如下:
public class VegVendor {
public void purchase(){
System.out.println("供应蔬菜……");
}
}
然后小明需要找妹妹来帮忙做饭,代码如下:
public class Helper {
public void cook(){
System.out.println("下厨烹饪……");
}
}
最后小明作为客户端类开始吃饭并洗碗,代码如下:
public class Client{
public void eat(){
System.out.println("开始用餐……");
}
public void wash(){
System.out.println("洗碗……");
}
public static void main(String[] args) {
//找蔬菜商买菜
VegVendor vegVendor = new VegVendor();
vegVendor.purchase();
//找妹妹下厨
Helper sister = new Helper();
sister.cook();
//客户端用餐
Client client = new Client();
client.eat();
//最后还得洗碗,确实有点麻烦
client.wash();
}
}
2. 去餐厅吃饭(提供门面方法)
虽然上面的代码不复杂,但是一整套流程下来还是很累人,如果烹饪方法再复杂些,或者是客户端对各个子系统的操作不当,那么就可能会出现更大的问题。
这是,小明开始意识到,任何事都亲力亲为的做法可能并不合适,专业的事情还是应该交给专业的人去完成,他们会把这些子系统的操作过程封装起来,再以更为便捷的方式提供给用户使用。
于是,小明决定了,去餐厅吃饭!!!!!
餐厅的工作流程如下:
public class Facade {
private VegVendor vegVendor;
private Chef chef;
private Waiter waiter;
private Cleaner cleaner;
public Facade() {
this.vegVendor = new VegVendor();
//开门前就找蔬菜商准备好蔬菜
vegVendor.purchase();
//雇佣厨师
this.chef = new Chef();
//雇佣服务员
this.waiter = new Waiter();
//雇佣清洁工、洗碗工等
this.cleaner = new Cleaner();
}
public void order(){
//接待,入座,点菜
waiter.order();
//找厨师做饭
chef.cook();
//上菜
waiter.serve();
//收拾桌子,洗碗,以及其他操作
cleaner.clean();
cleaner.wash();
}
}
餐厅里封装了大量的子系统资源,如蔬菜商、厨师、服务员、洗碗工等,并且对各个子系统依次进行了初始化操作。
而小明只需要调用 order() 方法就可以享受现成可口的饭菜了,操作变得简单而优雅。
总结
门面模式不但重要,而且其应用也非常广泛,最常见的是在我们日常工作开发中对多表更新操作,而且多表更新需要在一个事务里面进行。我们只需要对这些更新操作封装成一个 update 方法即可。如此一来,上层方法只需要调用这个 update 方法就可以进行更新了。
门面模式的各角色定义如下:
Facade(外观门面):封装了多个子系统,并将它们整合起来对外提供统一的访问接口。SubSystemA、SubSystemB、SubSystemC(子系统 A、子系统 B、子系统 C):隐藏于门面中的子系统,数量任意,且对外部不可见。对应本章例程中的蔬菜商类、厨师类、服务员类等。Client(客户端):门面系统的使用方,只访问门面提供的接口。
参考文档
- 《秒懂设计模式》—— 刘韬