java设计模式——策略模式
一. 定义与类型
定义:针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能。当代码中有大量的if...else...时,可以使用策略模式
类型:行为型。
二. 使用场景
(1) 系统有很多类,而他们的区别仅仅在于他们的行为不同
(2) 一个系统需要动态的几种算法中选择一种
三. 优缺点
优点:
(1) 符合开闭原则
(2) 避免使用多重条件转移语句
(3) 提高算法的保密性和安全性
缺点:
(1) 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
(2) 产生很多策略类
四. 相关设计模式
策略模式和工厂模式
策略模式和状态模式
五. Coding
先引入一个业务场景:假设在618和双十一的时候,各大电商会有各种促销;而促销就是课程的一个行为,但是这种促销行为有多种实现,网站里面的课程促销:
先创建一个促销策略接口:
/** * @program: designModel * @description: 促销策略接口 * @author: YuKai Fan * @create: 2019-02-13 16:47 **/ public interface PromotionStrategy { void doPromotion(); }
创建三个实现类分别代表各种策略,实现策略接口,立减策略:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:48 **/ public class LiJianPromotionStrategy implements PromotionStrategy { public void doPromotion() { System.out.println("立减促销,课程的价格直接减去配置的价格"); } }
返现策略:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:50 **/ public class FanXianPromotionStrategy implements PromotionStrategy { public void doPromotion() { System.out.println("返现促销,返回的金额存放到网站用户的余额中"); } }
满减策略:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:49 **/ public class ManJianPromotionStrategy implements PromotionStrategy { public void doPromotion() { System.out.println("满减促销,满200减20元"); } }
策略执行类:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:51 **/ public class PromotionActivity { private PromotionStrategy promotionStrategy; public PromotionActivity(PromotionStrategy promotionStrategy) { this.promotionStrategy = promotionStrategy; } public void executePromotionStrategy() { promotionStrategy.doPromotion(); } }
应用层:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:52 **/ public class Test { public static void main(String[] args) { //在618的时候,使用立减策略 PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy()); //在双11的时候,使用满减策略 PromotionActivity promotionActivity1111 = new PromotionActivity(new ManJianPromotionStrategy()); promotionActivity618.executePromotionStrategy(); promotionActivity1111.executePromotionStrategy(); } }
结果:
UML类图:
如果要修改业务,只需要新增一个策略类即可,还可以对上面的应用层进行改进
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:52 **/ public class Test { public static void main(String[] args) { PromotionActivity promotionActivity = null; //创建一个promotionKey String promotionKey = "LIJIAN"; if (StringUtils.equals(promotionKey, "LIJIAN")) { promotionActivity = new PromotionActivity(new LiJianPromotionStrategy()); } else if (StringUtils.equals(promotionKey, "FANXIAN")) { promotionActivity = new PromotionActivity(new FanXianPromotionStrategy()); }//.... promotionActivity.executePromotionStrategy(); }
结果:
还可以把策略模式和工厂模式结合到一起(为了避免空指针异常,可以创建一个空的促销策略):
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 17:10 **/ public class EmptyPromotionStrategy implements PromotionStrategy { public void doPromotion() { System.out.println("无促销"); } }
创建一个促销策略工厂类:
/** * @program: designModel * @description: 促销策略工厂的实现 * @author: YuKai Fan * @create: 2019-02-13 17:10 **/ public class PromotionStrategyFactory { private static Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, PromotionStrategy>(); static { PROMOTION_STRATEGY_MAP.put(PromotionKey.LIJIAN, new LiJianPromotionStrategy()); PROMOTION_STRATEGY_MAP.put(PromotionKey.FANXIAN, new FanXianPromotionStrategy()); PROMOTION_STRATEGY_MAP.put(PromotionKey.MANJIAN, new ManJianPromotionStrategy()); } private static final PromotionStrategy NON_PROMOTION = new EmptyPromotionStrategy(); private PromotionStrategyFactory() { } public static PromotionStrategy getNonPromotion(String promotionKey) { PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey); return promotionStrategy == null ? NON_PROMOTION : promotionStrategy; } private interface PromotionKey{ String LIJIAN = "LIJIAN"; String FANXIAN = "FANXIAN"; String MANJIAN = "MANJIAN"; } }
应用层:
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2019-02-13 16:52 **/ public class Test { public static void main(String[] args) { /** * 策略模式与工厂模式结合 */ String promotionKey = "LIJIAN"; PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getNonPromotion(promotionKey)); promotionActivity.executePromotionStrategy(); } }
结果:
策略模式一般都不会单独去使用,一般会结合单例,工厂方法,享元模式去使用
六. 源码分析