上一节给大家演示讲解了订单支付的业务流程中的各个步骤以及怎么在项目中进行微信支付的对接。不过现实的商品支付中一般会在收银台页面让用户选择以什么方式支付--是微信、支付宝或者是其他的什么支付、信用卡支付等等。
所以一般项目接入支付通道的时候不会只接入一种支付通道。这么干除了能避免依赖单一渠道的风险外,更多的还是因为互联网公司常见的营销玩法为了提高转化率会高度依赖多渠道多场景支付,比如各种签约支付、先用后付等等。
多场景支付的维护难度
随着项目接入的支付渠道越来越多、支持的支付场景和营销玩法越来越多,你的项目代码该怎么开发呢?大多数情况下就是一个支付场景一个if 条件分支呗,甚至新接入的支付渠道也可以是一个大的 if 代码分支、渠道的各种支付场景那就大分支里边套小分支呗。
长此以往代码的维护难度可想而之,到后期新加一个逻辑,为了保证上线不翻车,可能要把整个支付中的所有逻辑在测试阶段都回归一遍才敢上线。
那么有没有什么办法能让这种代码的发展别那么混乱,我希望给其中一个支付渠道的某类支付场景加了逻辑,测试时只回归对应的场景即可,有什么好办法吗?
这就是本节要给大家介绍的两个设计模式:模版模式和策略模式,我们通过把两种设计模式结合起来的使用来解决这些问题。
大家看一些开源或者设计好的项目的代码时会觉得好像它用了设计模式A,看了一会儿它咋又像设计模式B了,咋跟我学的设计模式的教程都不一样?我想说的是,有这种感觉就对了,用设计模式解决实际问题,通常是多种设计模式综合使用才能解决问题,单一设计模式能解决的问题还是太有限了。
本文节选自我的专栏《Go项目搭建和整洁开发实战》欢迎扫码订阅

订阅后除了加入实战项目外,还可加入专属读者群一起学习。
设计思路
接下来我们进入正题,怎么使用模版模式和策略模式来设计项目,让其以一个相对有序、可维护的发展趋势来支撑多渠道多场景支付呢?
我们从两个方面来思考这个问题:
这么多支付渠道,支付场景他们每次执行过程中有哪些共同点--即可提炼出来的标准化步骤?
找流程步骤中的可切步骤,有没有可能这个步骤的实现方式从A切换到了B,代码解决的流程就从A切换成了B?
如果你分析一通,发现没有? 那不好意思,不是你分析的不对,就是这两个模式确实用不上,那么咱就现有的代码打打补丁,能用就行了,哈哈哈。
接下在咱再说一下为啥要两种模式结合起来使用,其实很简单,使用它们时的设计思路有以下几点
模版限定流程的具体步骤(注:以下步骤请根据要实现的流程提炼出来,并不局限下面几种)
校验请求,检查必要参数
防抖防重,避免重复请求
准备流程中的必要参数:对于支付来说有订单数据、用户数据等
发起流程的关键步骤:支付流程就是发起相应的支付方式
生成响应
策略决定应该怎么支付 (各种支付平台的普通支付/签约代扣/....),返回给客户端什么样的结果。
设计实现
说了这么多,我估计大家都有点懵了,没办法首先要给大家解释清楚多支付渠道的多支付场景这个业务形态,其次应用上设计模式后代码纬度都会让整个代码设计的理解难度会大幅增加。
针对咱们今天的流程场景,我画了一个整个代码设计的UML类图:
首先我们定义接口 OrderPayTemplateContract,订单支付的模版--对订单支付执行过程的抽象, 模版方法中决定流程步骤的执行顺序。
type OrderPayTemplateContract interface { CreateOrderPay() (interface{}, error) // 模版方法 OrderPayHandlerContract }
OrderPayTemplateContract 中的CreateOrderPay 方法为模版方法,即在它的内部决定各个步骤的执行顺序,我们把流程步骤都放在了 OrderPayHandlerContract 接口中。
// OrderPayHandlerContract 订单支付的处理器接口--对订单支付各个主要步骤的抽象 type OrderPayHandlerContract interface { // CheckRepetition 防重校验 CheckRepetition() error // ValidateOrder 检验Order参数是否符合预期 ValidateOrder() error // LoadPayAndUserConfig 加载支付配置和支付平台需要的一些用户信息--比如微信的openID LoadPayAndUserConfig() error // LoadOrderPayStrategy 加载订单支付策略 LoadOrderPayStrategy() error // HandleOrderPay 发起支付 HandleOrderPay() (interface{}, error) }
步骤中有一个加载订单支付策略,我们定义了 OrderPayStrategyContract 支付策略接口,由其实现类去真正发起对支付平台的调用。
type OrderPayStrategyContract interface { // CreatePay 实现支付策略中有关创建支付的逻辑 // 可以根据策略本身决定去怎么实现 创建订单|设置签约码|...... CreatePay(ctx context.Context, order *do.Order, payConfig *OrderPayConfig) (interface{}, error) }
本文后续内容请扫码订阅专栏阅读完整版。
加入专栏后除了能获得完整版教程,更有配套的实战项目和专属读者群,我在其中用git tag版本编排好了每节教程对应的代码更新,让你能更容易地追踪项目开发过程中的每一处代码变更。
《Go项目搭建和整洁开发实战》专栏分为五大部分,重点章节如下
第一部分介绍让框架变得好用的诸多实战技巧,比如通过自定义日志门面让项目日志更简单易用、支持自动记录请求的追踪信息和程序位置信息、通过自定义Error在实现Go error接口的同时支持给给错误添加错误链,方便追溯错误源头。
第二部分:讲解项目分层架构的设计和划分业务模块的方法和标准,让你以后无论遇到什么项目都能按这套标准自己划分出模块和逻辑分层。后面几个部分均是该部分所讲内容的实践。
第三部分:设计实现一个套支持多平台登录,Token泄露检测、同平台多设备登录互踢功能的用户认证体系,这套用户认证体系既可以在你未来开发产品时直接应用
第四部分:商城app C端接口功能的实现,强化分层架构实现的讲解,这里还会讲解用责任链、策略和模版等设计模式去解决订单结算促销、支付方式支付场景等多种多样的实际问题。
第五部分:单元测试、项目Docker镜像、K8s部署和服务保障相关的一些基础内容和注意事项。
扫描上方二维码或者访问 https://xiaobot.net/p/golang 即刻订阅
此外想更详细地了解专栏内容,咨询专栏优惠,都可以添加下面我的微信