策略模式
策略模式(Strategy Pattern)是指定义了算法家族、分别封装起来,让它们之间可以互
相替换,此模式让算法的变化不会影响到使用算法的用户。
策略模式的应用场景
1、假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
2、一个系统需要动态地在几种算法中选择一种。
用策略模式实现选择支付方式的业务场景
大家都知道,我们咕泡学院的架构师课程经常会有优惠活动,优惠策略会有很多种可能
如:领取优惠券抵扣、返现促销、拼团优惠。下面我们用代码来模拟,首先我们创建一
个促销策略的抽象PromotionStrategy:
package com.gupaoedu.vip.pattern.strategy.promotion;
/**
* 促销策略抽象
* Created by Tom
*/
public interface PromotionStrategy {
void doPromotion();
}
然后分别创建优惠券抵扣策略CouponStrategy 类、返现促销策略CashbackStrategy
类、拼团优惠策略GroupbuyStrategy 类和无优惠策略EmptyStrategy 类:
CouponStrategy 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
/**
* 优惠券
* Created by Tom
*/
public class CouponStrategy implements PromotionStrategy {
public void doPromotion() {
System.out.println("领取优惠券,课程的价格直接减优惠券面值抵扣");
}}
CashbackStrategy 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
/**
* 返现活动
* Created by Tom
*/
public class CashbackStrategy implements PromotionStrategy {
public void doPromotion() {
System.out.println("返现促销,返回的金额转到支付宝账号");
}
}
GroupbuyStrategy 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
/**
* 拼团优惠
* Created by Tom
*/
public class GroupbuyStrategy implements PromotionStrategy{
public void doPromotion() {
System.out.println("拼团,满20 人成团,全团享受团购价");
}
}
EmptyStrategy 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
/**
* 无优惠
* Created by Tom
*/
public class EmptyStrategy implements PromotionStrategy {
public void doPromotion() {
System.out.println("无促销活动");
}
}
然后创建促销活动方案PromotionActivity 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void execute(){
promotionStrategy.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 类:
package com.gupaoedu.vip.pattern.strategy.promotion;
import java.util.HashMap;
import java.util.Map;
/**
* 促销策略工厂
* Created by Tom
*/
public class PromotionStrategyFactory {
private static Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String,
PromotionStrategy>();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
}
private static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();
private PromotionStrategyFactory(){}
public static PromotionStrategy getPromotionStrategy(String promotionKey){
PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
}
这时候我们客户端代码就应该这样写了:
public static void main(String[] args) {
String promotionKey = "GROUPBUY";
PromotionActivity promotionActivity = new
PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
promotionActivity.execute();
}
。相信小伙伴们都
用过支付宝、微信支付、银联支付以及京东白条。一个常见的应用场景就是大家在下单
支付时会提示选择支付方式,如果用户未选,系统也会默认好推荐的支付方式进行结算。
来看一下类图,下面我们用策略模式来模拟此业务场景: