美文网首页
策略模式

策略模式

作者: markeNick | 来源:发表于2021-09-06 21:51 被阅读0次

    概述

    利用多态,使得同一行为(方法)在不同场景下有不同的实现,并且将使用与实现分离。

    优点:

    • 能够解决if-else过多问题

    • 开闭原则,有新的策略时,只需要新建具体策略类即可

    缺点:

    • 策略类过多

    使用场景:

    • 需要动态地在几种算法中选择一种

    传统策略模式

    角色

    上下文类(Context):组合抽象策略类,注入具体策略类,实现调用不同策略实现

    抽象策略类(Strategy):定义公共接口

    具体策略类(ConcreteStrategy):实现抽象策略

    类图

    策略模式

    代码

    上下文类

    public class Context {
    
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        /**
         * 调用策略类
         */
        public void strategyMethod() {
            strategy.strategyMethod();
        }
    
        public Strategy getStrategy() {
            return strategy;
        }
    
        public void setStrategy(Strategy strategy) {
            this.strategy = strategy;
        }
    }
    

    抽象策略类

    public interface Strategy {
        
        void strategyMethod();
        
    }
    

    具体策略类A

    public class ConcreteStrategyA implements Strategy {
    
        @Override
        public void strategyMethod() {
            System.out.println("ConcreteStrategyA...");
        }
    
    }
    

    具体策略类B

    public class ConcreteStrategyB implements Strategy {
    
        @Override
        public void strategyMethod() {
            System.out.println("ConcreteStrategyB...");
        }
    
    }
    

    客户端

    public class Client {
    
        public static void main(String[] args) {
            Context context = new Context(new ConcreteStrategyA());
            context.strategyMethod();
        }
    }
    
    // 输出:ConcreteStrategyA...
    

    具体策略类自动生成

    上面存在的问题:Client需要显示去创建具体策略类,需要解耦,可以利用 Spring IOC,把上下文类替换为策略工厂类,然后具体策略类加上@Component注解

    类图

    策略模式 (2).png

    代码

    策略工厂类

    @Component
    public class StrategyFactory {
    
        /**
         * spring 会将所有Strategy类型注入进map
         * key就是bean的名称,value就是Strategy
         */
        @Autowired
        private Map<String, Strategy> strategyMap;
    
        /**
         * 调用策略类
         */
        public void strategyMethod(String key) {
            Strategy strategy = strategyMap.get(key);
            if (strategy != null) {
                strategy.strategyMethod();
            }
        }
    
    }
    

    具体策略类A

     /**
     * 具体策略类A
     */
    @Component(value = "ConcreteStrategyA")
    public class ConcreteStrategyA implements Strategy {
    
        @Override
        public void strategyMethod() {
            System.out.println("ConcreteStrategyA...");
        }
    
    }
    

    Map + Lambda表达式实现策略模式

    上面存在的问题:随着策略的增加,策略类数量势必增多,管理和维护难度也随之增加。另外,无法从宏观层面看到所有的策略实现类。

    策略选择器

    import javax.annotation.PostConstruct;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.function.Function;
    
    @Service
    public class StrategySelector {
    
        @Autowired
        private StrategyService strategyService;
    
        private  Map<String, Function<String, String>> strategyMap = new HashMap<>();
    
    
        @PostConstruct
        public void initMap() {
            strategyMap.put("f1", o -> strategyService.f1());
            strategyMap.put("f2", o -> strategyService.f2());
            strategyMap.put("f3", o -> strategyService.f3());
        }
    
        /**
         * 根据type获取对应策略
         */
        public String getResult(String type) {
            Function<String, String> function = strategyMap.get(type);
            if (function != null) {
                // 执行表达式获得对应结果
                return function.apply(type);
            }
    
            return null;
        }
    
    }
    

    策略实现类

    @Service
    class StrategyService {
    
        public String f1() {
            return "f1";
        }
    
        public String f2() {
            return "f2";
        }
    
        public String f3() {
            return "f3";
        }
    
    }
    

    利用Map+lambda实现策略模式,Map的value可以是Java 8 内置四大函数式接口

    相关文章

      网友评论

          本文标题:策略模式

          本文链接:https://www.haomeiwen.com/subject/ytmywltx.html