策略模式(Strategy Pattern)又叫作政策模式(Policy Pattern),它将定义的算法家族分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户,属于行为型设计模式。
    原理:面向对象的继承与多态

    场景:
    由客户端选择策略算法,解决if else或switch case带来的臃肿性问题
    (1)针对同一类型问题,有多种处理方式,每一种都能独立解决问题。
    (2)需要自由切换算法的场景。
    (3)需要屏蔽算法规则的场景。
    image.png
    Context上下文角色,用于操作策略的上下文环境,屏蔽高层模块对策略、算法的直接访问,隔离客户端于策略类的耦合

    1. public interface IStrategy {
    2. void doStrategy();
    3. }
    4. public class ConcreteStrategyA implements IStrategy{
    5. @Override
    6. public void doStrategy() {
    7. }
    8. }
    9. public class ConcreteStrategyB implements IStrategy{
    10. @Override
    11. public void doStrategy() {
    12. }
    13. }
    14. public class Context {
    15. private IStrategy strategy;
    16. public Context(IStrategy strategy) {
    17. this.strategy = strategy;
    18. }
    19. public void doStrategy(){
    20. this.strategy.doStrategy();
    21. }
    22. }
    23. public class Client {
    24. public static void main(String[] args){
    25. Context context = new Context(new ConcreteStrategyA());
    26. context.doStrategy();
    27. context = new Context(new ConcreteStrategyB());
    28. context.doStrategy();
    29. }
    30. }

    优点

    • 策略可以由客户端自由指定
    • 避免复杂if else,符合开闭原则

    缺点

    • 类膨胀
    • 所有策略类都需要对外暴露(可以配合工厂模式、享元模式等修正)

    如果策略类超过4个,就需要考虑使用混合模式解决类膨胀和对外暴露的问题,用工厂模式来实现策略类的声明

    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class StrategyFactory {
    
        private static Map<String,IStrategy> strategyMap = new ConcurrentHashMap<>();
    
        static {
            strategyMap.put(StrategyEnum.A.getCode(),StrategyEnum.A.getStrategy());
            strategyMap.put(StrategyEnum.B.getCode(),StrategyEnum.B.getStrategy());
        }
    
        private static IStrategy empty = new DefaultConcreteStrategy();
    
        public IStrategy getStrategy(String code){
            IStrategy iStrategy =  strategyMap.get(code);
            return iStrategy ==  null ? empty : iStrategy;
    
        }
    }
    
    public enum StrategyEnum {
        A("A",new ConcreteStrategyA()),
        B("B",new ConcreteStrategyB())
        ;
    
        StrategyEnum(String code, IStrategy strategy) {
            this.code = code;
            this.strategy = strategy;
        }
    
        private String code;
    
        private IStrategy strategy;
    
        public String getCode() {
            return code;
        }
    
        public IStrategy getStrategy() {
            return strategy;
        }
    }
    
    public class Client {
    
        public static void main(String[] args){
            String code = "A";
            StrategyFactory strategyFactory =  new StrategyFactory();
            IStrategy strategy = strategyFactory.getStrategy(code);
            strategy.doStrategy();
        }
    }
    

    框架

    • Comparator
    • Spring中Resource类
    • Spring初始化不同类型的类采用不同的初始化策略,InstantiationStrategy->SimpleInstantiationStrategy/CglibSubclassingInstantiationStrategy