重构支付接口(二)重构方案

上一篇博文描述了支付接口存在的问题:https://www.jianshu.com/p/0e801d1874d8
本篇博文描述我的重构思路。

一、使用简单工厂+策略模式解耦下单接口不同商品的下单逻辑

解耦前创建订单部分代码:

if (商品类型==A) {
    A商品下单逻辑,省略百来行代码
} else if (商品类型==B) {
    B商品下单逻辑,省略百来行代码
}......

解耦后的uml图如下:


工厂策略下单

将不同商品的下单逻辑放到AbstractProductPayStrategy下的商品类型对应实现子类中,下单部分的重复代码例如创建订单提取到AbstractProductStrategy父类,实现代码复用。

二、使用责任链重构价格计算逻辑

2.1重构前下单接口价格计算代码:

if (使用了优惠券) {
   价格 = 价格 - 优惠券面值;
}
if (参与活动A) {
   价格 = 原价 - 活动抵扣金额;
}
if (参与活动B && 商品类型 == A) {
   价格 = 价格 x 活动折扣;
}
if (没有使用优惠券) {
    // 活动C和活动D不能和优惠券叠加,有互斥关系
    if (参与活动C && 商品类型 == B) {

    }
    if (参与活动D && 商品类型 == C) {

    }
}

可以看到价格计算代码中有大量的营销活动逻辑,多种营销活动的优惠有叠加或者互斥关系,而且有的活动只适用于某几种商品,如果全用if else表达的话可读性极差,而且后期要增减营销活动和商品类型时会大量修改以上代码。

2.2使用责任链模式重构以上逻辑后的UML图:

营销活动责任链
  • 定义一个抽象处理器AbstractActivityHandler,责任链上的每一个活动处理器实现都集成该抽象类,next变量和setNext方法都是责任链模式原生代码,不做赘述。

  • AbstractActivityHandler的calcPrice用于计算活动优惠价格,所有的活动实现子类都实现calcPrice方法,内部是当前活动的优惠计算逻辑,当计算完当前活动的优惠价格后,调用next.calcPrice()方法,即可将价格计算流转到下一个活动。

  • 当calcPrice入参PriceRequest对象走完责任链上的所有环节后,便返回给调用方,此时的PriceRequest的price属性便是计算好所有营销活动优惠后的价格。

  • AbstractActivityHandler的callback用于处理第三方支付回调接口的活动后续逻辑,所有的活动实现子类都实现callback方法,内部是当前活动的支付成功处理逻辑,当用户拉起微信或支付宝支付完成,回调后端接口通知支付结果时,callback接口就会调用责任链进行活动后续逻辑处理,例如增加拼团日志,增加分销记录等。

重构后下单接口调用活动责任链计算价格的代码示例如下:

        // 假设我要购买课程,课程支持的活动有两个:优惠券和特价。可以将这两个活动组装到责任链中
        AbstractActivityHandler c = new CouponHandler();
        c.setNext(new SaleHandler());
        // 组装计算责任链入参
        Request request = new Request();
        // 这是商品原价
        request.setPrice(100);
        // 得到最终需要支付的价格
        Request r = c.calcPrice(request);

第一张UML图中我们用策略模式将不同商品的下单逻辑分离在各个Strategy实现类中,例如SubjectPayStrategy只组装课程适用的活动到责任链中。VipPayStrategy只组装vip适用的营销活动到责任链,实现了灵活组装营销活动和营销活动的代码复用。

上面的代码只能实现活动优惠叠加,如果责任链中的活动有互斥关系怎么办呢?
可以看到PriceRequest类中定义了几个属性:calculatedPin 、calculatedSale 、calculatedSell 、calculatedCoupon 、calculatedHelp ,记录已经计算了哪些活动的优惠,如果当前活动和已计算优惠的活动互斥,需要在活动处理器中调过当前活动的优惠计算,代码如下:

public class SaleHandler extends AbstractActivityHandler {

    @Override
    public Request calcPrice(PriceRequest request) {
        // 如果已经计算了优惠券优惠,就不能享受特价优惠
        if (request.calculatedCoupon()) {
            if (next != null) {
                // 直接流转到下一个活动
                return next.calcPrice(request);
            }
            return request;
        }
        省略计算限时特价优惠代码......
        request.setPrice(salePrice);
        request.setCalculatedSale(true);
        if (next != null) {
            // 流转到下一个活动
            return next.calcPrice(request);
        }
        return request;
    }
}

商品对应的PayStrategy拿到计算好的价格后,直接创建订单拉起调用第三方下单接口就完成了下单接口的所有操作。下单接口部分到此结束,接下来是支付成功回调接口。

三、使用简单工厂+策略模式解耦下单接口不同商品的支付成功完成订单逻辑

订单支付完成接口和下单接口一样,存在大量的商品类型和活动类型判断代码,用来处理不同商品和不同活动的支付成功后续逻辑,此处可以和下单接口一样,用简单工厂和策略处理,UML图如下:

使用简单工厂+策略模式重构支付成功回调后续逻辑的UML.png

取到下单接口流转完责任链的PriceRequest中的calculated相关字段信息,即可知道这个订单参与了哪些活动,组装好CallbackRequest,描述参与了哪些活动,经过责任链的callback方法流转,即可执行完成所有活动的支付成功处理逻辑。

以上就是我的支付接口重构思路,如果有不足的地方或者您有更好的方法,欢迎在评论区提出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容