定义
提供一个高层次的接口,使得子系统更易于使用
使用场景
当你的程序有很多个模块,或者说子系统。你希望给用户提供一个统一的操作界面类,而不是让用户分别与这些模块交互。
一种设计是:给用户提供一套面板方用来法完成一般性的功能,如果面板提供的方法不能满足用户需求,用户还可以直接使用具体模块的功能来达到自己的目的。
另一种设计是:用户完全看不到各子模块,所有操作必须通过面板来完成,如果面板没有提供相应的功能,那也就gg了。
如何使用
1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。
应用实例:
- 去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
- JAVA 的三层开发模式。
优点:
1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:
不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
uml 类图
角色
- Facade(外观)角色:提供一个外观接口,对外,它提供一个易于客户端访问的接口,对内,它可以访问子系统中的所有功能。
- SubSystem(子系统)角色:子系统在整个系统中可以是一个或多个模块,每个模块都有若干类组成,这些类可能相互之间有着比较复杂的关系。
实例
公司最近突然对正在开发的商城项目感了兴趣,所以要求出各种各样的报表。,因为公司要求的报表数据来自不同的子系统,这些子系统相互之间还有依赖,要想获得一份完整的报表,需要访问好多个模块
第一步,确定需要调用的子模块
确定我们要使用面板隐藏的子模块,此处假设有3个子模块
//订单系统
public class OrderSys {
public String getOrderNum(){
System.out.println("获取订单号");
return "123456";
}
}
//支付系统
public class PaymentSys {
private OrderSys orderSys;
public PaymentSys(OrderSys orderSys) {
this.orderSys = orderSys;
}
public BigDecimal getOrderAccount(String orderNum){
System.out.println(String.format("获取%s订单支付金额",orderNum));
return BigDecimal.valueOf(500);
}
}
//物流系统
public class DeliverySys {
public int getDeliveryTime(){
System.out.println("获取配送耗时");
return 30*60;//30分钟
}
}
第二步,创建外观类
这个模式实在是太简单了,基本没什么可说的。这个外观类就是引用其他功能模块,完成相关的功能对外暴露操作接口。
例如本例中的外观类ReportFacade使用了OrderSys 、PaymentSys与 DeliverySys 3个子模块来完成一个生成报表的功能,客户端只需要通过此方法就可以生成报表了,不用关心那些子模块。
public class ReportFacade {
private OrderSys orderSys ;
private PaymentSys paymentSys;
private DeliverySys deliverySys;
public ReportFacade(OrderSys orderSys, PaymentSys paymentSys, DeliverySys deliverySys) {
this.orderSys = orderSys;
this.paymentSys = paymentSys;
this.deliverySys = deliverySys;
}
public void generateReport() {
final String orderNum = orderSys.getOrderNum();
System.out.println(String.format("\n报表\n--------------------------------------------\n" +
"订单号:%s | 金额:%s元 | 配送耗时:%s分钟",
orderNum,
paymentSys.getOrderAccount(orderNum).toPlainString(),
String.valueOf(deliverySys.getDeliveryTime() / 60))
);
}
}
第三步,客户端使用
public class FacadeClient {
public static void main(String[] args) {
OrderSys orderSys = new OrderSys();
PaymentSys paymentSys = new PaymentSys(orderSys);
DeliverySys deliverySys = new DeliverySys();
new ReportFacade(orderSys, paymentSys, deliverySys).generateReport();
}
}
输出
获取订单号
获取158952578订单支付金额
获取配送耗时
报表
--------------------------------------------
订单号:158952578 | 金额:2550元 | 配送耗时:12分钟
可见客户端只于外观类交互,完全不用与具体的子模块交互。