作用
优点:定义算法家族,根据不同的策略封装不同的算法,达到松耦合目的,也提高算法的保密性,用户只需要调用相应的api即可
同时可以替代代码中出现的大量if-else代码块
假设要实现一个促销活动,促销活动有不同的方式,比如满减,返现
本次demo实现类似的逻辑
可以根据应用层的操作实现不同的策略
策略接口
提供一个促销方法供各个策略实现类实现
public interface PromotionStrategy {
/**
* 促销方法
*
* @return void
* @author YangYudi
* @date 2020/12/4 14:30
*/
void doPromotion();
}
策略类
每新增一个策略就创建一个实现策略接口的类
返现促销策略类
public class CashBackPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("返现促销");
}
}
满减促销策略类
public class FullReductionPromotionStrategy implements PromotionStrategy {
@Override
public 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
@AllArgsConstructor
public 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 {
@Override
public 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();
}