定义:
结构型门面模式(Facade Pattern)又叫外观模式,指提供了一个统一的接口用来访问子系统中的一群接口:定义一个高层接口,让子系统更容易使用,生活中常见的例子:前台接待员,包工头 ...
门面与代理:
门面模式重点在于封装,静态代理重点在于增强,可以说不做增强的静态代理就是门面模式
使用场景:
1.随着系统越来越复杂,可增加门面提供简单接口
2.构建多层系统结构,利用门面对象作为每层的入口简化层间调用
优点:
1.简化调用过程,无需深入了解子系统,以防给子系统带来风险
2.对于客户端而言减少系统依赖,松散耦合
3.更好的划分访问层次,提高安全性,例如MVC
4.遵循迪米特法则,即最少知道原则
缺点:
1.当增加子系统和扩展子系统行为时(修改),可能带来未知的风险
2.不符合开闭原则
3.某些情况下可能违背单一职责原则,当成为一个万能类时维护起来就很困难
示例:
/**
* 假设用积分下单,流程:
* 购买礼品->调启支付系统->调积分系统->调物流系统
*/
public class GiftInfo {
private String name;
public GiftInfo(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
// 支付
public class PaymentService {
private final static Logger logger = Logger.getLogger(PaymentService.class);
public boolean pay(GiftInfo gift){
logger.info("扣减" + gift.getName() + "积分成功");
return true;
}
}
// 积分
public class QualifyService {
private final static Logger logger = Logger.getLogger(PaymentService.class);
public boolean isAvailable(GiftInfo gift){
logger.info("验证" + gift.getName() + "积分通过,库存通过");
return true;
}
}
// 物流
public class ShippingService {
private final static Logger logger = Logger.getLogger(PaymentService.class);
public String delivery(GiftInfo gift){
logger.info(gift.getName() + "物流运送中 ..");
// 返回物流单号
return "5788698";
}
}
/**
* 门面
*/
public class FacedeService {
private final static Logger logger = Logger.getLogger(FacedeService.class);
private PaymentService pay = new PaymentService();
private QualifyService qualify = new QualifyService();
private ShippingService shipping = new ShippingService();
public void exchange(GiftInfo gift){
if(pay.pay(gift)){
if(qualify.isAvailable(gift)){
String ShippingNum = shipping.delivery(gift);
logger.info("下单成功,物流单号是:" + ShippingNum);
}
}
}
}
// 模拟客户端
public class MainExcute {
private final static Logger logger = Logger.getLogger(MainExcute.class);
public static void main(String[] args) {
// 未使用门面之前
GiftInfo gift = new GiftInfo("《Spring5 核心原理》");
PaymentService pay = new PaymentService();
QualifyService qualify = new QualifyService();
ShippingService shipping = new ShippingService();
if(pay.pay(gift)){
if(qualify.isAvailable(gift)){
String ShippingNum = shipping.delivery(gift);
logger.info("下单成功,物流单号是:" + ShippingNum);
}
}
// 使用门面之后,客户端只需要调用一个接口
FacedeService facede = new FacedeService();
facede.exchange(gift);
/**
* 门面模式在源码中的应用
* tomcat中也用的比较多,例:RequestFacede,ResponseFacede 类中
*/
}
}
类图:
image.png