文章首发在公众号(龙台的技术笔记),之后同步到 segmentfault 和集体网站:xiaomage.info

明天和大家聊一聊,如何正当的将多种设计模式放到同一个业务场景中

业务背景

最近接到一个认证的需要,C 端用户在购买公司保险时,须要先进行 实名认证确认身份

为了保障业务复用,独自将认证的逻辑拆分为微服务模块

C 端用户下单购买保险的逻辑大抵如下

先说下对于认证相干的一些基本知识。简略来说,你如何证实你是你本人

一些云服务厂商都会有对于验证身份的付费接口,接下来咱们就以腾讯云姓名、身份证二因素认证为参考进行举例

说完认证常识,咱们再来拆解下用户购买保险的步骤

  1. 用户在前端发动认证行为
  2. 申请通过网关调用保险服务,保险服务调用认证服务
  3. 认证服务调用腾讯云认证付费 API,返回认证后果信息

认证流程

在整个块认证流程中,咱们会解说三种设计模式,依照程序别离是策略、责任链、模板模式

策略模式

定义一组算法类,将每个算法别离封装起来,让它们能够相互替换。策略模式使这些算法在客户端调用它们的时候可能互不影响地变动,客户端代指应用算法的代码

咱们拿认证来说,定义一个认证接口,而后实现二、三、四因素以及人脸识别实现;将这些实现类放到一个 Map 容器中,并和业务规定好对应的标识 Key,通过标识 Key 获取对应的认证策略实现

如果真的像下面这么简略,if-else 判断加上拆解几个认证函数就能够搞得定,还真的不肯定须要策略模式

咱们再延长来看一种简单场景:假如后续不满足于腾讯云的认证,为了保障可用性以及更多的流量,须要对接更多的认证平台

可用性:平台的接口不太可能保障全年百分百可用,须要有容灾降级或者替换计划

更多的流量:腾讯云认证接口限流 100次 / S

这个时候策略模式的长处就体现进去了,简化代码的复杂性 以及 保障开闭准则,减少程序的健壮性以及可扩展性

后续再减少三方认证平台和认证形式,都不须要改变原有逻辑,增加对应实现即可

责任链模式

在责任链模式中,多个处理器(参照拦截器)顺次解决同一个申请。一个申请先通过 A 处理器解决,而后再把申请传递给 B 处理器,B 处理器解决完后再传递给 C 处理器,以此类推,造成一个链条,链条上的每个处理器 各自承当各自的解决职责

这里次要将责任链模式利用于,躲避无意义调用三方认证服务

  1. 已认证过的人员信息,在有效期内没必要再次调用
  2. 调用认证后果谬误,仍然会扣钱,比如说名称中蕴含非中文,身份证格局谬误等等

咱们能够将处理器尽量职责繁多,不便后续其它认证形式的 复用和编排

模板办法

模板办法模式在一个办法中定义一个 算法骨架,并将某些步骤推延到 子类中实现。模板办法模式能够让子类在 不扭转算法整体构造的状况下,从新定义算法中的某些步骤

模版办法次要作用:复用性扩展性

  • 复用性:核心思想就是 父级定义公共实现由子级进行调取应用
  • 扩展性:在不批改办法逻辑的前提下,变更其中的某些步骤

艰深来讲 : 定义一个抽象类 AbstractTemplate,并定义一个或若干形象办法 abstractMethod。代码大抵如下:

public abstract class AbstractAuthenticationService<T extends AuthenticationRequest> {    void before(T request) {    }    void after(T request) {    }      // 形象办法    protected abstract void practicalExecute(T request);    public void authentication(T request) {          // 前置拦挡操作,包含不限于责任链模式调用        before(request);          // 策略模式实现,调用具体认证类,比方二因素认证或三要素认证        practicalExecute(request);          // 资源清理或记录认证实现信息        after(request);    }

腾讯云二因素认证实现类,代码如下:

@Slf4j@Component@RequiredArgsConstructor// BaseAuthenticationStrategy 是策略模式实现,定义了 mark、execute 办法public class NameIdCardAuthenticationByTencentResolver extends AbstractAuthenticationService<NameIdCardAuthenticationReqDTO>        implements BaseAuthenticationStrategy<NameIdCardAuthenticationReqDTO> {    private static final String SUCCESS = "0";      // 责任链容器    private final NameIdCardHandlerChain nameIdCardHandlerChain;    @Override    public String mark() {        return AuthenticationEnum.TENCENT.name();    }    @Override    public void execute(NameIdCardAuthenticationReqDTO request) {        authentication(request);    }    @Override    public void before(NameIdCardAuthenticationReqDTO request) {          // 责任链调用        nameIdCardHandlerChain.doFilter(request);    }    @Override    public void practicalExecute(NameIdCardAuthenticationReqDTO request) {        // 腾讯云二因素认证具体行为    }}

最初总结

抛出一个陈词滥调的问题,学习设计模式有什么作用?

设计模式次要是为了应答 代码的复杂性,让其满足 开闭准则,进步代码的 扩展性;适合的场景正当使用的设计模式,能够帮忙代码实现 高内聚、低耦合 等的长处

你无奈决定他人的代码,但你能够决定本人的。工夫短缺的状况下,尽量以重构的形式去写每一行代码

最初心愿小伙伴读过文章后有所播种,祝好。