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 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 Paymen 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 t {
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 + ‘’’ +
‘}’;
}
}