跳至主要內容

【设计模式】结构型-③门面模式

holic-x...大约 6 分钟设计模式设计模式

【设计模式】结构型-③门面模式

学习核心

  • 门面模式核心

    • 概念:提供统一接口,用于访问一组子系统的功能(例如酒店门面对接,说需求然后达到相应目的),门面负责统一对接、分发请求,用户不需要关注背后的逻辑
    • 组成:门面角色、子系统角色(一个或多个)
  • 应用

    • 【search-platform】聚合接口:提供聚合接口(统一搜索入口),减少接口交互、简化交互成本,提升应用性能

概念说明

​ 门面模式(Facade Pattern) 又叫外观模式, 提供了一个统一的接口, 用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构性模式。

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。其实,在日常的编码工作中,都在有意无意地大量使用门面模式,但凡只要高层模块需要调度多个子系统(2个以上类对象),我们都会自觉地创建一个新类封装这些子系统,提供精简接口,让高层模块可以更加容易间接调用这些子系统的功能。尤其是现阶段各种第三方SDK, 各种开源类库,很大概率都会使用门面模式(尤其是觉得调用越方便的,门面模式使用的一般更多)

​ 门面模式主要包括2种角色:

  • 外观角色(Facades) :也称门面角色, 系统对外的统一接口;
  • 子系统角色(SubSystem):可以同时有一个或者多个SubSystem,每个SubSystem都不是一个单独的类, 而是一个类的集合。SubSystem并不知道Facade的存在, 对于SubSystem而言, Facade只是另一个客户端而已(即Facade对SubSystem透明)

场景案例分析

1.聚合搜索接口

门面模式概念

​ 目的:门面模式的主要目的是提供一个 统一的接口,用于访问一组子系统的功能。

​ 使用门面模式可以简化接口,降低调用方的使用和理解成本;它封装了子系统的复杂性,使客户端可以更轻松地与子系统交互,而不需要了解子系统内部的工作细节,降低了客户端和子系统的耦合度。

​ 例如在search-platform项目中,一开始构想的是通过不同方式搜索,每个搜索触发都去请求一次接口,但是这对前后端数据交互、包括前后端开发调试来说成本都相对较高,于是调整为将所有的搜索入口统一为一个入口,后端controller对外统一提供一个接口供数据交互,根据前端指定的不同searchType搜索类型进行校验,进而匹配相应的搜索结果。这种模式相当于将前端的一些工作量丢到后台处理,但是在实际交互上能够很大程度改善系统性能,常见使用门面模式的还有slfj4框架

​ 门面模式的场景:例如当调用多个系统接口觉得繁琐的时候可以考虑引入(门面充当于前台角色,是负责统一接收、分发请求的,而客户端不需要关注后端具体做了什么事情,只需要按照既定规则传递参数即可),贴合生活场景案例,当我们想要定一个酒店房间,只需要找到前台提供身份证号和房间需求,然后按照操作指示完成任务即可

具体实现方式:

(1)定义门面类:创建一个门面类,该类充当客户端和多个子系统之间的中介。门面类包含了对多个子系统的引用,并提供了封装接口,供客户端使用。

(2)封装操作:在门面类中,根据输入参数,选择调用不同的数据源搜索服务来搜索数据,并将其结果进行合并、转换处理,以生成最终统一的聚合结果。

(3)提供简化接口:前端通过与门面类交互来执行搜索操作,而不需要了解每个数据源具体的搜索过程。

​ 构建聚合接口,针对不同的查找参数,统一对外提供一个入口进行调用。定义门面SearchFacade(定义doSearch方法,统一入参出参),随后通过调用方法实现不同类型的数据搜索

// 1.定义门面
public class SearchFacade{
  // 提供方法供外部调用:确认出参入参
  SearchVO doSearch(String searchType){
    // 根据不同筛选类型查找参数
  }
}

// 2.调用门面方法
SearchFacade searchFacade = new SearchFacade();
searchFacade.doSearch("xxx");

img

2.积分礼品兑换

​ 以积分礼品兑换为例,在礼品商城中的大部分功能并不是全部重新开发的, 而是要去对接已有的各个子系统。这些子系统可能涉及到积分系统、支付系统、物流系统的接口调用。如果所有的接口调用全部由前端发送网络请求去调用现有接口的话,一则会增加前端开发人员的难度以及前后端的交互成本,二则会增加一些网络请求影响页面性能。这个时候就可以发挥门面模式的优势了,可以将所有现成的接口全部整合到一个类中,由后端提供统一的接口给前端调用,这样前端开发人员就不需要关心各接口的业务关系,只需要把精力集中在页面交互上

​ 设定积分兑换的步骤涉及校验、支付、物流三个核心,在没有引入门面模式的情况下,前端可能需要与后台进行多次交互完成一整个兑换步骤。通过引入门面模式,将多个子系统的交互整合到一个接口中,由后台统一做子系统的调用处理,简化了前后端的交互成本

/**
 * 礼品兑换:门面模式
 * 礼品兑换涉及到一系列流程:校验、支付、物流等
 */
public class GiftExchangeFacadeDemo {
    // 定义礼品兑换交互核心参数
    static class Gift {
        int id;
        String name;
    }

    // ① 模拟多个子系统服务(校验、支付、物流)
    // 校验服务
    static class QualifyService {
        public boolean isAvailable(Gift gift) {
            // todo 礼品兑换校验
            System.out.println("校验" + gift.name + "礼品兑换(积分和库存)");
            return true;
        }
    }

    // 支付服务
    static class PayService {
        public boolean pay(Gift gift) {
            // todo 礼品节分扣减
            System.out.println(gift.name + "礼品积分扣减成功");
            return true;
        }
    }

    // 物流服务
    static class ShippingService {
        public String delivery(Gift gift) {
            // todo 物流处理
            String shippingNo = "123456";
            System.out.println(gift.name + "发货成功,物流编号为" + shippingNo);
            return shippingNo;
        }
    }

    // ② 门面类:整合一组子系统的服务
    static class GiftFacade {

        // 定义一组子系统服务
        QualifyService qualifyService = new QualifyService();
        PayService payService = new PayService();
        ShippingService shippingService = new ShippingService();

        public void exchange(Gift gift) {
            // a.校验
            if (qualifyService.isAvailable(gift)) {
                // b.积分扣减
                if (payService.pay(gift)) {
                    // c.发货
                    String shippingNo = shippingService.delivery(gift);
                    System.out.println("商品兑换成功,商品已发货,物流单号为:" + shippingNo);
                }
            }
        }

    }

    public static void main(String[] args) {
        // 定义要兑换的礼品信息
        Gift gift = new Gift();
        gift.name = "iphone 12";
        gift.id = 1;

        GiftFacade giftFacade = new GiftFacade();
        giftFacade.exchange(gift);
    }

}
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3