这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情
系列文章|源码
定义-是什么
外观模式(Facade Pattern)又叫门面模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构性模式。
门面模式主要包含两种角色:
- 外观角色(Facade):也称门面角色,系统对外的统一接口。
- 子系统角色(SubSystem):可以同时有一个或多个SubSystem。每个SubSystem都不是一个单独的类,而是一个类的集合。SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另一个客户端而已(即Facade对SubSystem透明)。
思考-为什么
应用场景
- 子系统越来越复杂,增加门面模式提供简单接口。
- 构建多层系统结构,利用门面对象作为每层的入口,简化层间调用。
优点
- 简化了调用过程,无需深入了解系统,防止给子系统带来风险。
- 减少系统依赖,松散耦合。
- 更好的划分访问层次,提高了安全性。
- 遵循迪米特法则,即最少知道原则。
缺点
- 当增加子系统和扩展子系统行为时,可能容易带来未知风险。
- 不符合开闭原则。
- 某些情况下可能违背单一职责原则。
应用-怎么用
案例:积分兑换
商城系统中,有积分兑换的模块,兑换积分可能涉及到的模块有:①库存校验系统;②积分支付系统;③物流系统;
相关代码
/**
* 积分礼物
*/
public class PointsGift {
private String name;
public PointsGift(String name) {
this.name = name;
}
@Override
public String toString() {
return "PointsGift{" +
"name='" + name + ''' +
'}';
}
}
/**
* 资格校验:积分校验,库存校验
*/
public class QualifyService {
public boolean isAvailable(PointsGift pointsGift) {
System.out.println("校验" + pointsGift + " 积分通过,库存通过");
return true;
}
}
/**
* 积分支付服务
*/
public class PointsPaymentService {
public boolean pay(PointsGift pointsGift) {
System.out.println(pointsGift + " 支付扣减积分成功");
return true;
}
}
/**
* 物流服务
*/
public class ShippingService {
public String shipGift(PointsGift pointsGift) {
// 物流系统对接逻辑
System.out.println(pointsGift + " 进入物流系统");
String shippingOrderNo = "6666";
return shippingOrderNo;
}
}
三个子系统服务,外部如果要使用,必须知道流程,这个时候就可以封装一个外观服务; 一个积分礼物兑换的服务暴露,这也符合迪米特法则,即最少知道原则;
修改后代码:
/**
* 外观模式服务
*/
public class GiftExchangeService {
private QualifyService qualifyService;
private PointsPaymentService pointsPaymentService;
private ShippingService shippingService;
public GiftExchangeService(QualifyService qualifyService, PointsPaymentService pointsPaymentService, ShippingService shippingService) {
this.qualifyService = qualifyService;
this.pointsPaymentService = pointsPaymentService;
this.shippingService = shippingService;
}
/**
* 礼物兑换
*/
public void giftExchange(PointsGift pointsGift) {
if (qualifyService.isAvailable(pointsGift)
&& pointsPaymentService.pay(pointsGift)) {
String shippingOrderNo = shippingService.shipGift(pointsGift);
System.out.println(pointsGift + " 返回的订单号 " + shippingOrderNo);
}
}
}
/**
* 测试代码
*/
@Test
public void giftExchange() {
GiftExchangeService giftExchangeService = new GiftExchangeService(new QualifyService(), new PointsPaymentService(), new ShippingService());
giftExchangeService.giftExchange(new PointsGift("iphone15"));
}
=====================
校验PointsGift{name='iphone15'} 积分通过,库存通过
PointsGift{name='iphone15'} 支付扣减积分成功
PointsGift{name='iphone15'} 进入物流系统
PointsGift{name='iphone15'} 返回的订单号 6666