文章首发在公众号(龙台的技术笔记),之后同步到 segmentfault 和集体网站:xiaomage.info
明天和大家聊一聊,如何正当的将多种设计模式放到同一个业务场景中
业务背景
最近接到一个认证的需要,C 端用户在购买公司保险时,须要先进行 实名认证确认身份
为了保障业务复用,独自将认证的逻辑拆分为微服务模块
C 端用户下单购买保险的逻辑大抵如下
先说下对于认证相干的一些基本知识。简略来说,你如何证实你是你本人
一些云服务厂商都会有对于验证身份的付费接口,接下来咱们就以腾讯云姓名、身份证二因素认证为参考进行举例
说完认证常识,咱们再来拆解下用户购买保险的步骤
- 用户在前端发动认证行为
- 申请通过网关调用保险服务,保险服务调用认证服务
- 认证服务调用腾讯云认证付费 API,返回认证后果信息
认证流程
在整个块认证流程中,咱们会解说三种设计模式,依照程序别离是策略、责任链、模板模式
策略模式
定义一组算法类,将每个算法别离封装起来,让它们能够相互替换。策略模式使这些算法在客户端调用它们的时候可能互不影响地变动,客户端代指应用算法的代码
咱们拿认证来说,定义一个认证接口,而后实现二、三、四因素以及人脸识别实现;将这些实现类放到一个 Map 容器中,并和业务规定好对应的标识 Key,通过标识 Key 获取对应的认证策略实现
如果真的像下面这么简略,if-else 判断加上拆解几个认证函数就能够搞得定,还真的不肯定须要策略模式
咱们再延长来看一种简单场景:假如后续不满足于腾讯云的认证,为了保障可用性以及更多的流量,须要对接更多的认证平台
可用性:平台的接口不太可能保障全年百分百可用,须要有容灾降级或者替换计划
更多的流量:腾讯云认证接口限流 100次 / S
这个时候策略模式的长处就体现进去了,简化代码的复杂性 以及 保障开闭准则,减少程序的健壮性以及可扩展性
后续再减少三方认证平台和认证形式,都不须要改变原有逻辑,增加对应实现即可
责任链模式
在责任链模式中,多个处理器(参照拦截器)顺次解决同一个申请。一个申请先通过 A 处理器解决,而后再把申请传递给 B 处理器,B 处理器解决完后再传递给 C 处理器,以此类推,造成一个链条,链条上的每个处理器 各自承当各自的解决职责
这里次要将责任链模式利用于,躲避无意义调用三方认证服务
- 已认证过的人员信息,在有效期内没必要再次调用
- 调用认证后果谬误,仍然会扣钱,比如说名称中蕴含非中文,身份证格局谬误等等
咱们能够将处理器尽量职责繁多,不便后续其它认证形式的 复用和编排
模板办法
模板办法模式在一个办法中定义一个 算法骨架,并将某些步骤推延到 子类中实现。模板办法模式能够让子类在 不扭转算法整体构造的状况下,从新定义算法中的某些步骤
模版办法次要作用:复用性 和 扩展性
- 复用性:核心思想就是 父级定义公共实现,由子级进行调取应用
- 扩展性:在不批改办法逻辑的前提下,变更其中的某些步骤
艰深来讲 : 定义一个抽象类 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) { // 腾讯云二因素认证具体行为 }}
最初总结
抛出一个陈词滥调的问题,学习设计模式有什么作用?
设计模式次要是为了应答 代码的复杂性,让其满足 开闭准则,进步代码的 扩展性;适合的场景正当使用的设计模式,能够帮忙代码实现 高内聚、低耦合 等的长处
你无奈决定他人的代码,但你能够决定本人的。工夫短缺的状况下,尽量以重构的形式去写每一行代码
最初心愿小伙伴读过文章后有所播种,祝好。