大家好,欢迎来到IT知识分享网。
设计模式之门面模式详解
一、什么是门面模式
门面模式(Facade Pattern) 又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口 。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型模式。在我们日常编码中也在无意中大量的使用着门面模式,例如
ServiceA中调用其他多个Service的方法,然后再将ServiceA的方法暴露给Controller调用,ServiceA就相当于一个门面使得Controller能够间接的调用其他Service子系统,这也就是门面模式的一种应用。
二、门面模式的应用场景
- 子系统越来越复杂,增加门面模式提供简单接口
- 构建多层系统结构,利用门面对象作为每层的入口,简化层间调用
三、门面模式的角色组成
- 外观角色(Facade): 也称门面角色,系统对外的统一接口;
- 子系统角色(
SubSystem): 可以同时有一个或多个SubSystem。每个SubSystem都不是一个单独的类,而是一个类的集合。SubSystem并不知道Facade 的存在,对于SubSystem而言,Facade只是另外一个客户端而已(即Facade对SubSystem是透明的)。
四、门面模式通用写法
我们先分别创建3个子系统的业务逻辑SubSystemA、SubSystemB、SubSystemC
/ * 子系统角色 - SubSystemA * * @author zdp * @date 2022/9/3 14:38 */ public class SubSystemA {
public void doA() {
System.out.println("doing A stuff"); } }
/ * 子系统角色 - SubSystemB * * @author zdp * @date 2022/9/3 14:38 */ public class SubSystemB {
public void doB() {
System.out.println("doing B stuff"); } }
/ * 子系统角色 - SubSystemC * * @author zdp * @date 2022/9/3 14:38 */ public class SubSystemC {
public void doC() {
System.out.println("doing C stuff"); } }
紧接着再创建一个外观角色类Facade :
/ * 外观角色 Facade 相当于注入其他Service,封装其方法暴露给客户端 * * @author zdp * @date 2022/9/3 14:34 */ public class Facade {
//相当于@Autowire注入 private SubSystemA a = new SubSystemA(); private SubSystemB b = new SubSystemB(); private SubSystemC c = new SubSystemC(); // 对外接口 public void doA() {
this.a.doA(); } // 对外接口 public void doB() {
this.b.doB(); } // 对外接口 public void doC() {
this.c.doC(); } }
编写测试类
/ * facade 通用写法 * * @author zdp * @date 2022/9/3 14:36 */ class Test {
// 客户 (相当于Controller) public static void main(String[] args) {
Facade facade = new Facade(); facade.doA(); facade.doB(); facade.doC(); } }
五、门面模式在业务中的应用
需求:现有积分、支付、库存、物流系统,需要做一个积分兑换商城
- 创建商品类
/ * 商品详情信息 * * @author zdp * @date 2022/9/3 14:52 */ @Data @Builder public class GoodsInfo {
private String name; private Integer integral; private BigDecimal price; }
- 积分系统
/ * 积分系统 * * @author zdp * @date 2022/9/3 14:51 */ @Slf4j public class IntegralSystem {
/ * 扣减积分 * * @param info GoodsInfo * @author zdp * @date 2022/9/3 15:10 * @return result */ public boolean deductIntegral(GoodsInfo info){
log.info("商品【{}】扣减积分成功", info.getName()); return true; } }
- 库存系统
/ * 库存系统 * * @author zdp * @date 2022/9/3 14:54 */ @Slf4j public class StockSystem {
public static int goodsStock = 2; / * 扣减库存 * * @param info GoodsInfo * @author zdp * @date 2022/9/3 15:07 * @return result */ public boolean deductStock(GoodsInfo info){
goodsStock -= 1; if (goodsStock < 0) {
log.info("商品【{}】扣减库存失败,库存不足~", info.getName()); return false; } log.info("商品【{}】扣减库存成功~", info.getName()); return true; } }
- 支付系统
/ * 支付系统 * * @author zdp * @date 2022/9/3 14:52 */ @Slf4j public class PaymentSystem {
StockSystem stock = new StockSystem(); IntegralSystem integral = new IntegralSystem(); / * 付款 * * @param info GoodsInfo * @author zdp * @date 2022/9/3 15:08 * @return result */ public boolean pay(GoodsInfo info){
if (stock.deductStock(info)) {
integral.deductIntegral(info); log.info("商品【{}】支付成功,准备发货~", info.getName()); return true; } return false; } }
- 物流系统
/ * 物流系统 * * @author zdp * @date 2022/9/3 14:49 */ @Slf4j public class LogisticsSystem {
/ * 对接物流系统,商品发货 * * @param info goods info * @author zdp * @date 2022/9/3 14:57 * @return java.lang.String 物流单号 */ public void deliverGoods(GoodsInfo info){
//对接物流系统... log.info("商品【{}】,进入物流系统,单号: {}", info.getName(), new Date().getTime()); } }
- 外观角色门面
/ * 外观角色 Facade 商品兑换门面 整合了支付和物流系统,使得前端开发逻辑处理简单,不用再调用多个系统 * * @author zdp * @date 2022/9/3 15:15 */ public class GoodsFacadeSystem {
PaymentSystem payment = new PaymentSystem(); LogisticsSystem logistics = new LogisticsSystem(); / * 商品兑换 * * @param info GoodsInfo * @author zdp * @date 2022/9/3 15:16 * @return 商品兑换结果 */ public boolean exchange(GoodsInfo info){
if (!payment.pay(info)) {
return false; } logistics.deliverGoods(info); return true; } }
- 测试
public class Test {
public static void main(String[] args) throws Exception{
GoodsFacadeSystem facade = new GoodsFacadeSystem(); for (int i = 0; i < 3; i++) {
GoodsInfo info = GoodsInfo.builder() .name("拖孩儿") .integral(100) .price(new BigDecimal("10.05")) .build(); facade.exchange(info); TimeUnit.MILLISECONDS.sleep(1); } } }
六、门面模式优缺点
- 优点
- 简化了调用过程,无需深入了解子系统,以防给子系统带来风险
- 减少系统依赖,松散耦合
- 更好地划分访问层次,提高了安全性
- 遵循迪米特法则,即最少知道原则
- 缺点
- 当增加子系统和扩展子系统行为时,可能容易带来风险
- 不符合开闭原则
- 某些情况下可能违背单一职责原则
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/116474.html
