1、什么是策略模式(Strategy Pattern)
策略模式(Strategy Pattern)是指定义了算法家族并分别封装起来,让它们之间可以相互替换,此模式使得算法的变化不会 影响使用算法的用户。
2、策略模式的应用场景
策略模式的应用场景如下:
- 系统中有很多类,而它们的区别仅仅在于其行为不同。
- 一个系统需要动态的在几种算法之间选择一种。
3、策略模式的成员结构
策略模式有以下三种角色构成
- 抽象策略类:定义所有支持的算法公共接口。
- 具体策略实现类:实现抽象策略接口实现具体的算法策略。
- 环境类(Context):维护一个策略抽象类的对象引用,可以定义接口让抽象策略类访问它的数据。
策略模式实现步骤:
- 定义抽象策略类
- 实现具体的策略类
- 定义环境类
4、用策略模式实现商场打折促销的业务场景
每逢节日商场都会有打折促销的活动,但是优惠策略有很多种,如满减优惠、优惠券抵扣、积分抵扣、会员折扣等。现在我们应用策略模式来模拟这个场景,按照策略模式的实现步骤,首先创建一个优惠策略接口PromotionStrategy。
public interface PromotionStrategy {
void doPromotion();
}
然后分别创建满减优惠策略类FullDiscountStrategy、优惠券抵扣CouponDiscountStrategy、积分抵扣IntegralDiscountStrategy去实现优惠策略接口PromotionStrategy。
FullDiscountStrategy类如下:
public class FullDiscountStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.print("满减优惠活动:满400减50!");
}
}
CouponDiscountStrategy类如下:
public class CouponDiscountStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.print("优惠券抵扣活动:50抵扣100!");
}
}
IntegralDiscountStrategy类如下:
public class IntegralDiscountStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.print("积分抵扣活动:1000积分抵扣100!");
}
}
最后创建一个策略环境类 PromotionContext:
public class PromotionContext {
private PromotionStrategy promotionStrategy;
public PromotionContext(PromotionStrategy promotion) {
this.promotionStrategy = promotion;
}
public void doPromotion() {
this.promotionStrategy.doPromotion();
}
}
然后我们简单写一个main方法测试一下:
public static void main(String[] args) {
// 调用满减策略
PromotionContext fullDiscount = new PromotionContext(new FullDiscountStrategy());
fullDiscount.doPromotion();
// 调用积分策略
PromotionContext integralDiscount = new PromotionContext(new IntegralDiscountStrategy());
integralDiscount.doPromotion();
// 调用优惠券策略
PromotionContext couponDiscount = new PromotionContext(new CouponDiscountStrategy());
couponDiscount.doPromotion();
}
这里我们会发现,上面这种测试代码在实际开发场景当中并不实用,因为实际的业务场景往往要根据不同的需求对促销策略进行动态选择,并不会一次性执行多种策略。可能有的时候我们的代码会这么写:
public static void main(String[] args) {
PromotionContext context = null;
String promotionKey = "COUPON";
if(promotionKey.equals("COUPON")) {
context = new PromotionContext(new CouponDiscountStrategy());
} else if(promotionKey.equals("FULL")) {
context = new PromotionContext(new FullDiscountStrategy());
} else if(promotionKey.equals("INTEGRAL")) {
context = new PromotionContext(new IntegralDiscountStrategy());
}
context.doPromotion();
}
这种虽然满足了业务需求,但是随着业务的不断发展和促销活动越来越多,判断逻辑也就会随着越来越冗长。现在我们可以通过结合单例模式和工厂模式来进行优化。创建PromotionStrategyFactory类:
public class PromotionStrategyFactory {
private static Map<String,PromotionStrategy> PROMOTION_STATEGY_MAP = new HashMap<>();
static {
PROMOTION_STATEGY_MAP.put(PromotionKey.COUPON, new CouponDiscountStrategy());
PROMOTION_STATEGY_MAP.put(PromotionKey.FULL, new FullDiscountStrategy());
PROMOTION_STATEGY_MAP.put(PromotionKey.INTEGRAL, new IntegralDiscountStrategy());
}
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 FULL = "FULL";
String INTEGRAL = "INTEGRAL";
}
}
这时候客户端的代码就应该这样写了:
public static void main(String[] args) {
String promotionKey = "COUPON";
PromotionContext context = new PromotionContext(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
context.doPromotion();
}