桥接模式之多融资场景多交易的设计方案

一、需求描述

还是基于《消失的字段》和《消失的消息》两篇文章中提到的供应链金融项目。该项目支持多种融资模式,比如:应收账款(YSZK)融资、活体质押(HTZY)融资、预付信用(YFXY)融资等。不同的融资模式业务流程不尽相同,包含不同的请求交易;即使相同的请求交易,交易请求报文也可能不一样。

针对这种情况,如果设计不合理,将导致类的数量暴增。假如5个场景,每个场景3个交易请求,各不相同,就要处理15种请求,如果每种请求都由一个服务实现类处理,则需要15个实现类(只有这样子才能保证遵循开闭原则)。如果扩展一个场景,则需要增加3个类;如果增加一个交易请求,则需要增加5个类。

根据以上的描述,采用桥接模式来实现该需求的设计开发,既能控制类数量暴增的情况,同时也能满足开闭原则。

二、设计方案

先上一张UML类图,如下:

桥接模式之多融资场景多交易的设计方案_第1张图片

上图设计了3个接口:

  • BankBaseService: 该接口提供统一发送请求报文到银行端的服务,只包含一个方法sendToBank,类BankBaseServiceImpl实现该发送逻辑;
  • BankService: 定义了全面的融资服务接口,包括:准入申请、授信申请、融资申请3个方法,不同场景分别实现该接口,包含3个实现类;
  • BankParamBuilder: 定义了构建融资服务接口请求报文的接口,包括:构建准入申请请求报文、授信申请请求报文、融资申请请求报文3个方法,不同场景分别实现该接口,包含3个实现类;

接下来,贴出应收账款融资场景的相关类代码:

@Service
public interface BankBaseService {
    Resp sendToBank(PubHeadReq head, T body, String serviceUrl);
}

@Service
public class BankBaseServiceImpl implements BankBaseService {
    @Override
    Resp sendToBank(PubHeadReq head, T body, String serviceUrl) {
          // 向银行发送请求报文逻辑
          ...  
    }
}
@Service
public interface BankParamBuilder {

    // 构建银行接口-企业准入申请的参数
    BankParam buildEnterpriseInfoApply(BizHeadReq head, JSONObject body) throws Exception;

    // 构建银行接口-授信申请的参数
    BankParam buildCreditApply(BizHeadReq head, JSONObject body) throws Exception;

    // 构建银行接口-融资申请的参数
    BankParam buildFinanceApply(BizHeadReq head, JSONObject body) throws Exception;
}

// 应收账款融资场景银行接口请求报文构建实现类
@Service("yszkBankParamBuilder")
public class TradeDebtBankParamBuilder implements BankParamBuilder {
    // 构建不同交易的请求报文
    ...
}
@Service
public interface BankService {
    // 企业准入申请
    BaseBodyResp enterpriseInfoApply(BizHeadReq head, JSONObject body) throws Exception;
    // 授信申请
    BaseBodyResp creditApply(BizHeadReq head, JSONObject body) throws Exception;
    // 融资申请
    BaseBodyResp financeApply(BizHeadReq head, JSONObject body) throws Exception;
}

// 应收账款融资场景银行接口服务实现类
@Service
public class YSZKBankServiceImpl extends BankBaseServiceImpl implements BankService {

    @Autowired
    private BankParamBuilder yszkBankParamBuilder;

    @Override
    public BankBaseBodyResp enterpriseInfoApply(BizHeadReq head, JSONObject body) throws Exception {
        // 构建银行接口请求参数
        BankParam bankParam = yszkBankParamBuilder.buildEnterpriseInfoApply(head, body);
        // 发送参数到银行接口服务
        return sendToBank(bankParam.getHead(), bankParam.getBody(), bankParam.getServiceUrl());
    }

    @Override
    public BankBaseBodyResp creditApply(BizHeadReq head, JSONObject body) throws Exception {
        throw new Exception("应收账款融资场景不支持接口申请授信!");
    }

    @Override
    public BankBaseBodyResp financeApply(BizHeadReq head, JSONObject body) throws Exception {
        // 构建银行接口请求参数
        BankParam bankParam = yszkBankParamBuilder.buildFinanceApply(head, body);
        // 构建银行接口请求参数
        return sendToBank(bankParam.getHead(), bankParam.getBody(), bankParam.getServiceUrl());
    }
 }

三、总结

桥接模式很好地解决了多维度关联扩展问题。如果新增一个融资场景,只需要增加两个类:BankService接口的实现类和BankParamBuilder接口的实现类,与交易请求方法数量无关,而且本次扩展不会影响原来场景的实现代码。

可能读者会发现一个问题,如果BankService接口增加一个交易方法呢,其当前各个场景的实现类代码都需要调整。这个问题,可以从业务角度考虑,提前考虑整个融资流程中涉及的所有需要与银行交互的交易,这个流程在各个银行应该都有一套固定业务流程,是可以提前考虑全面的。

另外,即使新增了一个交易,也并不需要全部场景都要实现,允许某些融资场景不支持一些银行交易。比如:YSZKBankServiceImpl代码中就不支持通过接口实现授信申请,必须去柜台办理。

你可能感兴趣的:(桥接模式)