作用

优点:定义算法家族,根据不同的策略封装不同的算法,达到松耦合目的,也提高算法的保密性,用户只需要调用相应的api即可

同时可以替代代码中出现的大量if-else代码块

假设要实现一个促销活动,促销活动有不同的方式,比如满减,返现

本次demo实现类似的逻辑

可以根据应用层的操作实现不同的策略

策略接口

提供一个促销方法供各个策略实现类实现

  1. public interface PromotionStrategy {
  2. /**
  3. * 促销方法
  4. *
  5. * @return void
  6. * @author YangYudi
  7. * @date 2020/12/4 14:30
  8. */
  9. void doPromotion();
  10. }

策略类

每新增一个策略就创建一个实现策略接口的类

返现促销策略类

  1. public class CashBackPromotionStrategy implements PromotionStrategy {
  2. @Override
  3. public void doPromotion() {
  4. System.out.println("返现促销");
  5. }
  6. }

满减促销策略类

  1. public class FullReductionPromotionStrategy implements PromotionStrategy {
  2. @Override
  3. public void doPromotion() {
  4. System.out.println("满减促销");
  5. }
  6. }

促销活动类

用来调用促销策略,可以对促销策略进行封装,此处写的比较简单

  1. public class PromotionActivity {
  2. /**
  3. * 促销策略
  4. */
  5. private PromotionStrategy promotionStrategy;
  6. public PromotionActivity(PromotionStrategy promotionStrategy) {
  7. this.promotionStrategy = promotionStrategy;
  8. }
  9. /**
  10. * 执行促销活动
  11. */
  12. public void executePromotion() {
  13. promotionStrategy.doPromotion();
  14. }
  15. }

应用层调用

根据不同的场景实现不同的策略

  1. public static void main(String[] args) {
  2. String promotion = "618";
  3. //促销活动类
  4. PromotionActivity promotionActivity = null;
  5. //618执行满减策略
  6. if ("618".equals(promotion)) {
  7. promotionActivity = new PromotionActivity(new FullReductionPromotionStrategy());
  8. }
  9. //双十一执行返现策略
  10. if ("1111".equals(promotion)) {
  11. promotionActivity = new PromotionActivity(new CashBackPromotionStrategy());
  12. }
  13. promotionActivity.executePromotion();
  14. }

但是这里有一个问题

这样写并不能替换大量的if-else代码块

使用枚举类优化

根据不同的code得到不同的策略,向外提供一个接口获得策略

  1. @Getter
  2. @AllArgsConstructor
  3. public enum PromotionStrategyEnum {
  4. /**
  5. * 根据不同的code查询不同策略
  6. */
  7. CASH_BACK(1111, new CashBackPromotionStrategy()),
  8. FULL(618, new FullReductionPromotionStrategy()),
  9. EMPTY(null, new EmptyPromotionStrategy());
  10. private Integer code;
  11. private PromotionStrategy promotionStrategy;
  12. public static PromotionStrategy getPromotionStrategy(Integer code) {
  13. if (ObjectUtils.isEmpty(code)) {
  14. return EMPTY.getPromotionStrategy();
  15. }
  16. for (PromotionStrategyEnum strategyEnum : PromotionStrategyEnum.values()) {
  17. if (strategyEnum.getCode().equals(code)) {
  18. return strategyEnum.getPromotionStrategy();
  19. }
  20. }
  21. return null;
  22. }
  23. }

服务调用也就简单了

  1. public static void main(String[] args) {
  2. Integer promotion = 618;
  3. PromotionStrategy promotionStrategy = PromotionStrategyEnum.getPromotionStrategy(promotion);
  4. PromotionActivity promotionActivity = new PromotionActivity(promotionStrategy);
  5. promotionActivity.executePromotion();
  6. }

策略工厂模式整合

创建一个策略工厂类来获取对应策略,和枚举类的方式相似

策略工厂类

使用一个HashMap来保存策略和策略key的键值对,通过key来获取对应的策略

  1. public class PromotionStrategyFactory {
  2. /**
  3. * 用于保存策略
  4. */
  5. private static final Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new ConcurrentHashMap<>();
  6. /**
  7. * 空策略
  8. */
  9. private static final PromotionStrategy EMPTY_PROMOTION_STRATEGY = new EmptyPromotionStrategy();
  10. static {
  11. //在此添加策略
  12. PROMOTION_STRATEGY_MAP.put(PromotionKey.FULL_REDUCTION, new FullReductionPromotionStrategy());
  13. PROMOTION_STRATEGY_MAP.put(PromotionKey.CASH_BACK, new CashBackPromotionStrategy());
  14. }
  15. private PromotionStrategyFactory() {
  16. }
  17. public static PromotionStrategy getPromotionStrategy(String promotionKey) {
  18. PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
  19. //如果没有就执行一个空策略
  20. return promotionStrategy == null ? EMPTY_PROMOTION_STRATEGY : promotionStrategy;
  21. }
  22. /**
  23. * 策略key 可通过应用层传入的值来获取对应的策略
  24. */
  25. private interface PromotionKey {
  26. /**
  27. * 策略值
  28. */
  29. String FULL_REDUCTION = "fullReduction";
  30. String CASH_BACK = "cashBack";
  31. }
  32. }

如果需要设计新的策略,就需要新建策略类,并在策略工厂类里添加即可

空策略

策略工厂类可以通过应用层传入的值来获取对应的策略

如果传入的值没有就返回一个空策略

  1. public class EmptyPromotionStrategy implements PromotionStrategy {
  2. @Override
  3. public void doPromotion() {
  4. System.out.println("无促销");
  5. }
  6. }

应用层调用

  1. public static void main(String[] args) {
  2. PromotionActivity promotionActivity = null;
  3. String promotionKey = "fullRedxxxxuction";
  4. //根据传入的值来获取策略 避免了大量的if-else语句
  5. PromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey);
  6. //促销活动类
  7. promotionActivity = new PromotionActivity(promotionStrategy);
  8. promotionActivity.executePromotion();
  9. }