文章目录
- 一、概念
- 二、策略模式的生活场景
- 三、适用场景
- 三、角色构成
- 四、业务场景示例
- 总结
- 优点
- 缺点
一、概念
- 策略模式(Strategy Pattern)又叫政策模式(Policy Pattern),属于行为型模式。
- 通过面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。
二、策略模式的生活场景
- 个人的交税率与他的工资有关。
- 支付方式的选择,微信支付,支付宝支付,银联支付。
三、适用场景
- 针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
- 算法需要自由切换的场景;
- 需要屏蔽算法规则的场景。
三、角色构成
上下文角色(Context): 用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化;
抽象策略角色(Strategy): 规定策略或算法的行为
具体策略角色(ConcreteStrategy): 具体的策略或算法实现
四、业务场景示例
优惠活动
- 创建促销粗略对象PromotionStrategy
/*** <p>* 促销策略对象* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public interface IPromotionStrategy {/*** 执行促销操作*/void doPromotion();
}
- 创建优惠券抵扣策略对象
/*** <p>* 优惠券策略* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public class CouponStrategy implements IPromotionStrategy{@Overridepublic void doPromotion() {System.out.println("使用优惠券抵扣");}
}
- 创建返现促销策略对象CashbackStrategy
/*** <p>* 返现策略* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public class CashbackStrategy implements IPromotionStrategy{@Overridepublic void doPromotion() {System.out.println("返现,直接打款到支付宝帐号");}
}
- 创建拼团优惠策略对象
/*** <p>* 团购策略* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public class GroupbuyStrategy implements IPromotionStrategy{@Overridepublic void doPromotion() {System.out.println("5人成团,可以优惠");}
}
- 无优惠策略对象
/*** <p>* 无优惠* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public class EmptyStrategy implements IPromotionStrategy{@Overridepublic void doPromotion() {System.out.println("无优惠");}
}
- 创建促销活动方案
/*** <p>* 促销活动方案* </p>** @author shiqi* @version 1.0.0* @createTime 2023-11-16*/
public class PromotionActivity {private IPromotionStrategy promotionStrategy;@SuppressWarnings("all")public PromotionActivity(IPromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}/*** 执行促销策略*/public void executePromotionStrategy() {promotionStrategy.doPromotion();}}
- 编写客户端测试类
public class Test {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.executePromotionStrategy();}
}
此客户端弊端在于if else太多了,随着业务的扩展只会越来越臃肿,所以需要改造。
- 创建促销策略工厂类
public class PromotionStrategyFactory {public static Map<String,IPromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();static {PROMOTION_STRATEGY_MAP.put(PromotionKey.EMPTY,new EmptyStrategy());PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());}public interface PromotionKey{String EMPTY = "EMPTY";String COUPON = "COUPON";String CASHBACK = "CASHBACK";String GROUPBUY = "GROUPBUY";}/*** 获取促销策略的键集合** @return 促销策略的键集合*/public static Set<String> getPromotionStrategyKeys(){return PROMOTION_STRATEGY_MAP.keySet();}/*** 根据促销码获取促销策略* @param promotionKey 促销码* @return 促销策略*/public static IPromotionStrategy getPromotionStrategy(String promotionKey){return PROMOTION_STRATEGY_MAP.get(promotionKey);}}
- 改写客户端
public class Test {public static void main(String[] args) {// 获取促销策略String promotionKey= "COUPON";IPromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey);promotionStrategy.doPromotion();}
}
总结
优点
- 策略模式符合开闭原则
- 避免使用多重条件转移语句,如if…else…语句,switch语句
- 使用策略模式可以提高算法的保密性和安全性。
缺点
- 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
- 代码中会产生非常多策略类,增加维护难度。