作用
优点:定义算法家族,根据不同的策略封装不同的算法,达到松耦合目的,也提高算法的保密性,用户只需要调用相应的api即可
同时可以替代代码中出现的大量if-else代码块
假设要实现一个促销活动,促销活动有不同的方式,比如满减,返现
本次demo实现类似的逻辑
可以根据应用层的操作实现不同的策略
策略接口
提供一个促销方法供各个策略实现类实现
public interface PromotionStrategy {/*** 促销方法** @return void* @author YangYudi* @date 2020/12/4 14:30*/void doPromotion();}
策略类
每新增一个策略就创建一个实现策略接口的类
返现促销策略类
public class CashBackPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("返现促销");}}
满减促销策略类
public class FullReductionPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("满减促销");}}
促销活动类
用来调用促销策略,可以对促销策略进行封装,此处写的比较简单
public class PromotionActivity {/*** 促销策略*/private PromotionStrategy promotionStrategy;public PromotionActivity(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}/*** 执行促销活动*/public void executePromotion() {promotionStrategy.doPromotion();}}
应用层调用
根据不同的场景实现不同的策略
public static void main(String[] args) {String promotion = "618";//促销活动类PromotionActivity promotionActivity = null;//618执行满减策略if ("618".equals(promotion)) {promotionActivity = new PromotionActivity(new FullReductionPromotionStrategy());}//双十一执行返现策略if ("1111".equals(promotion)) {promotionActivity = new PromotionActivity(new CashBackPromotionStrategy());}promotionActivity.executePromotion();}
但是这里有一个问题
使用枚举类优化
根据不同的code得到不同的策略,向外提供一个接口获得策略
@Getter@AllArgsConstructorpublic enum PromotionStrategyEnum {/*** 根据不同的code查询不同策略*/CASH_BACK(1111, new CashBackPromotionStrategy()),FULL(618, new FullReductionPromotionStrategy()),EMPTY(null, new EmptyPromotionStrategy());private Integer code;private PromotionStrategy promotionStrategy;public static PromotionStrategy getPromotionStrategy(Integer code) {if (ObjectUtils.isEmpty(code)) {return EMPTY.getPromotionStrategy();}for (PromotionStrategyEnum strategyEnum : PromotionStrategyEnum.values()) {if (strategyEnum.getCode().equals(code)) {return strategyEnum.getPromotionStrategy();}}return null;}}
服务调用也就简单了
public static void main(String[] args) {Integer promotion = 618;PromotionStrategy promotionStrategy = PromotionStrategyEnum.getPromotionStrategy(promotion);PromotionActivity promotionActivity = new PromotionActivity(promotionStrategy);promotionActivity.executePromotion();}
策略工厂模式整合
策略工厂类
使用一个HashMap来保存策略和策略key的键值对,通过key来获取对应的策略
public class PromotionStrategyFactory {/*** 用于保存策略*/private static final Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new ConcurrentHashMap<>();/*** 空策略*/private static final PromotionStrategy EMPTY_PROMOTION_STRATEGY = new EmptyPromotionStrategy();static {//在此添加策略PROMOTION_STRATEGY_MAP.put(PromotionKey.FULL_REDUCTION, new FullReductionPromotionStrategy());PROMOTION_STRATEGY_MAP.put(PromotionKey.CASH_BACK, new CashBackPromotionStrategy());}private PromotionStrategyFactory() {}public static PromotionStrategy getPromotionStrategy(String promotionKey) {PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);//如果没有就执行一个空策略return promotionStrategy == null ? EMPTY_PROMOTION_STRATEGY : promotionStrategy;}/*** 策略key 可通过应用层传入的值来获取对应的策略*/private interface PromotionKey {/*** 策略值*/String FULL_REDUCTION = "fullReduction";String CASH_BACK = "cashBack";}}
如果需要设计新的策略,就需要新建策略类,并在策略工厂类里添加即可
空策略
策略工厂类可以通过应用层传入的值来获取对应的策略
如果传入的值没有就返回一个空策略
public class EmptyPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("无促销");}}
应用层调用
public static void main(String[] args) {PromotionActivity promotionActivity = null;String promotionKey = "fullRedxxxxuction";//根据传入的值来获取策略 避免了大量的if-else语句PromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey);//促销活动类promotionActivity = new PromotionActivity(promotionStrategy);promotionActivity.executePromotion();}
