乐趣区

关于java:使用策略模式重构电商折扣和支付场景

1 应用策略模式实现促销优惠计划抉择

大家都晓得,咕泡学院的架构师课程常常会有优惠活动,优惠策略有很多种可能,如支付优惠券抵扣、返现促销、拼团优惠等。上面用代码来模仿,首先创立一个促销策略的形象 PromotionStrategy。


/**
 * 促销策略形象
 * Created by Tom.
 */
public interface IPromotionStrategy {void doPromotion();
}

而后别离创立优惠券抵扣策略 CouponStrategy 类、返现促销策略 CashbackStrategy 类、拼团优惠策略 GroupbuyStrategy 类和无优惠策略 EmptyStrategy 类。
CouponStrategy 类的代码如下。


public class CouponStrategy implements IPromotionStrategy {public void doPromotion() {System.out.println("应用优惠券抵扣");
    }
}

CashbackStrategy 类的代码如下。


public class CashbackStrategy implements IPromotionStrategy {public void doPromotion() {System.out.println("返现,间接打款到支付宝账号");
    }
}

GroupbuyStrategy 类的代码如下。


public class GroupbuyStrategy implements IPromotionStrategy {public void doPromotion() {System.out.println("5 人成团,能够优惠");
    }
}

EmptyStrategy 类的代码如下。


public class EmptyStrategy implements IPromotionStrategy {public void doPromotion() {System.out.println("无优惠");
    }
}

接着创立促销流动计划 PromotionActivity 类。


public class PromotionActivity {
    private IPromotionStrategy strategy;

    public PromotionActivity(IPromotionStrategy strategy) {this.strategy = strategy;}

    public void execute(){strategy.doPromotion();
    }
}

最初编写客户端测试代码。


public static void main(String[] args) {PromotionActivity activity618 = new PromotionActivity(new CouponStrategy());
    PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy());

    activity618.execute();
    activity1111.execute();}

此时,小伙伴们会发现,如果把下面这段客户端测试代码放到理论的业务场景中,其实并不实用。因为咱们做流动的时候往往要依据不同的需要对促销策略进行动静抉择,并不会一次性执行多种优惠。所以代码通常会这样写。


public static void main(String[] args) {
    PromotionActivity promotionActivity = null;

    String promotionKey = "COUPON";

    if(StringUtils.equals(promotionKey,"COUPON")){promotionActivity = new PromotionActivity(new CouponStrategy());
    }else if(StringUtils.equals(promotionKey,"CASHBACK")){promotionActivity = new PromotionActivity(new CashbackStrategy());
    }//......
    promotionActivity.execute();}

这样革新之后,代码满足了业务需要,客户可依据本人的需要抉择不同的优惠策略。然而,通过一段时间的业务积攒,促销流动会越来越多。于是,程序员就开始常常加班,每次上流动之前都要通宵改代码,而且要做反复测试,判断逻辑可能也会变得越来越简单。此时,咱们要思考代码是否须要重构。回顾之前学过的设计模式,咱们应该如何来优化这段代码呢?其实,能够联合单例模式和简略工厂模式,创立 PromotionStrategyFactory 类。


public class PromotionStrategyFacory {private static Map<String,IPromotionStrategy> PROMOTIONS = new HashMap<String, IPromotionStrategy>();

    static {PROMOTIONS.put(PromotionKey.COUPON,new CouponStrategy());
        PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy());
        PROMOTIONS.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
    }

    private static final IPromotionStrategy EMPTY = new EmptyStrategy();

    private PromotionStrategyFacory(){}

    public static IPromotionStrategy getPromotionStrategy(String promotionKey){IPromotionStrategy strategy = PROMOTIONS.get(promotionKey);
        return strategy == null ? EMPTY : strategy;
    }
    private interface PromotionKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";
    }

    public static  Set<String> getPromotionKeys(){return PROMOTIONS.keySet();
    }
}

这时候,客户端测试代码如下。


public static void main(String[] args) {PromotionStrategyFacory.getPromotionKeys();
        String promotionKey = "COUPON";

        IPromotionStrategy promotionStrategy = PromotionStrategyFacory.getPromotionStrategy (promotionKey);
        promotionStrategy.doPromotion();}

代码优化之后,程序员的保护工作也变得轻松了。每次上新流动都不影响原来的代码逻辑。

2 应用策略模式重构领取形式抉择场景

为了加深对策略模式的了解,咱们再举一个案例。置信小伙伴们都用过支付宝、微信领取、银联领取及京东白条,一个常见的利用场景就是大家在下单领取时会提醒抉择领取形式,如果用户未选,零碎也会默认好举荐的领取形式进行结算。来看如下图所示的类图,咱们用策略模式来模仿此业务场景。

首先创立 Payment 抽象类,定义领取标准和领取逻辑,代码如下。


import com.tom.pattern.strategy.pay.PayState;

/**
 * 领取渠道
 * Created by Tom.
 */
public abstract class Payment {public abstract String getName();

    // 通用逻辑被放到抽象类里实现
    public MsgResult pay(String uid, double amount){
        // 余额是否足够
        if(queryBalance(uid) < amount){return new MsgResult(500,"领取失败","余额有余");
        }
        return new MsgResult(200,"领取胜利","领取金额" + amount);
    }

    protected abstract double queryBalance(String uid);
}

而后别离创立具体的领取形式,支付宝 AliPay 类的代码如下。


public class AliPay extends Payment {public String getName() {return "支付宝";}

    protected double queryBalance(String uid) {return 900;}
}

京东白条 JDPay 类的代码如下。



public class JDPay extends Payment {public String getName() {return "京东白条";}

    protected double queryBalance(String uid) {return 500;}
}

微信领取 WechatPay 类的代码如下。


public class WechatPay extends Payment {public String getName() {return "微信领取";}

    protected double queryBalance(String uid) {return 263;}
}

银联领取 UnionPay 类的代码如下。


public class UnionPay extends Payment {public String getName() {return "银联领取";}

    protected double queryBalance(String uid) {return 120;}
}

接着创立领取状态的包装类 MsgResult。


/**
 * 领取实现当前的状态
 * Created by Tom.
 */
public class MsgResult {
    private int code;
    private Object data;
    private String msg;

    public MsgResult(int code, String msg, Object data) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "MsgResult{" +
                "code=" + code +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }
}

创立领取策略管理类。


import java.util.HashMap;
import java.util.Map;

/**
 * 领取策略管理
 * Created by Tom.
 */
public class PayStrategy {
    public static  final String ALI_PAY = "AliPay";
    public static  final String JD_PAY = "JdPay";
    public static  final String WECHAT_PAY = "WechatPay";
    public static  final String UNION_PAY = "UnionPay";
    public static  final String DEFAULT_PAY = ALI_PAY;

    private static Map<String,Payment> strategy = new HashMap<String,Payment>();

    static {strategy.put(ALI_PAY,new AliPay());
        strategy.put(JD_PAY,new JDPay());
        strategy.put(WECHAT_PAY,new WechatPay());
        strategy.put(UNION_PAY,new UnionPay());
    }

    public static Payment get(String payKey){if(!strategy.containsKey(payKey)){return strategy.get(DEFAULT_PAY);
        }
        return strategy.get(payKey);
    }
}

创立订单 Order 类。


import com.tom.pattern.strategy.pay.payport.PayStrategy;
import com.tom.pattern.strategy.pay.payport.Payment;

/**
 * Created by Tom.
 */
public class Order {
    private String uid;
    private String orderId;
    private double amount;

    public Order(String uid, String orderId, double amount) {
        this.uid = uid;
        this.orderId = orderId;
        this.amount = amount;
    }

    public MsgResult pay(){return pay(PayStrategy.DEFAULT_PAY);
    }

    public MsgResult pay(String payKey){Payment payment = PayStrategy.get(payKey);
        System.out.println("欢送应用" + payment.getName());
        System.out.println("本次交易金额为" + amount + ",开始扣款");
        return payment.pay(uid,amount);
    }
}

最初编写客户端测试代码。


public static void main(String[] args) {Order order = new Order("1","2020031401000323",324.5);
        System.out.println(order.pay(PayStrategy.ALI_PAY));
}

运行后果如下图所示。

通过常见的业务场景举例,心愿小伙伴们可能更粗浅地了解策略模式。

【举荐】Tom 弹架构:珍藏本文,相当于珍藏一本“设计模式”的书

本文为“Tom 弹架构”原创,转载请注明出处。技术在于分享,我分享我高兴!
如果本文对您有帮忙,欢送关注和点赞;如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源。关注微信公众号『Tom 弹架构』可获取更多技术干货!

退出移动版