门面模式说明
它能将多个不同的子系统接口封装起来,并对外提供统一的高层接口,使复杂的子系统变得更易使用
为了达到高效、便捷的目的,门店会统一对子系统进行整合与调度
外观门面类内部封装了大量的子系统资源
在实际场景中可能还会包含一些更加复杂的逻辑
实际业务场景
业务逻辑层(Service层)对数据访问层(DAO层)的调用可能包含多个步骤,除此之外还要进行事务处理,最终统一对外提供一个update()方法,如此一来上层(如控制器Controller层)便可一步调用
软件模块应该只专注于各自擅长的领域,合理明确的分工模式才能更好地整合与共享资源。这正是门面模式所解决的问题,其中外观门面类对子系统的整合与共享极大地保证了用户访问的便利性,作为核心模块,其重要性不言而喻
门面模式的各角色定义如下
- Facade(外观门面):封装了多个子系统,并将它们整合起来对外提供统一的访问接口。
- SubSystemA、SubSystemB、SubSystemC(子系统A、子系统B、子系统C):隐藏于门面中的子系统,数量任意,且对外部不可见。对应本章例程中的蔬菜商类、厨师类、服务员类等。
- Client(客户端):门面系统的使用方,只访问门面提供的接口。
对客户端这种“门外汉”来说,直接使用子系统是复杂而烦琐的,门面则充当了包装类的角色,对子系统进行整合,再对外暴露统一接口,使其结构内繁外简,最终达到资源共享、简化操作的目的。从另一方面讲,门面模式也降低了客户端与子系统之间的依赖度,高内聚才能低耦合
代码实现
package com.azure.design.facade;
/**
* 门面类,整合了多个子系统的调用
*/
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();
}
}
public class VegVendor {
public void purchase() {
System.out.println("购买蔬菜");
}
}
public class Chef {
public void cook() {
System.out.println("厨师做菜");
}
}
public class Waiter {
public void order() {
System.out.println("服务员下单");
}
public void serve() {
System.out.println("服务员上菜");
}
}
public class Cleaner {
public void clean() {
System.out.println("清洁工清洁");
}
public void wash() {
System.out.println("清洁工洗碗");
}
}
public class Client {
public static void main(String[] args) {
// 创建门面对象
Facade facade = new Facade();
// 只需要调用门面系统对外暴露的方法,无需关系内部结构即可
facade.order();
}
}
引用资料
刘韬《秒懂设计模式》