美文网首页spring
如何使用 Spring 实现策略模式+工厂模式

如何使用 Spring 实现策略模式+工厂模式

作者: 程序员阿远 | 来源:发表于2022-04-07 21:24 被阅读0次

    一、策略模式

    策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换

    1、策略模式主要角色

    image.png

    主要角色如下:

    • 封装角色(Context): 也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化
    • 抽象策略角色(Strategy): 策略家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
    • 具体策略角色(ConcreteStrategy): 实现抽象策略中的操作,该类含有具体的算法

    2、实现策略模式

    //抽象策略角色
    public interface Strategy {
        //策略模式的运算法则
        void doSomething();
    }
    
    
    //具体策略角色
    public class ConcreteStrategy1 implements Strategy {
        @Override
        public void doSomething() {
            System.out.println("具体策略1的运算法则...");
        }
    }
    
    
    //具体策略角色
    public class ConcreteStrategy2 implements Strategy {
        @Override
        public void doSomething() {
            System.out.println("具体策略2的运算法则...");
        }
    }
    
    
    public class Client {
        public static void main(String[] args) {
            //声明一个具体的策略
            Strategy strategy = new ConcreteStrategy1();
            //声明上下文对象
            Context context = new Context(strategy);
            //执行封装后的方法
            context.doAnything();
        }
    }
    
    

    执行结果如下:

    具体策略1的运算法则...
    
    

    二、使用Spring实现策略模式+工厂模式

    1、实现策略类

    public interface Strategy {
        //策略模式的运算法则
        void doSomething();
    }
    
    
    @Component
    public class ConcreteStrategy1 implements Strategy {
        @Override
        public void doSomething() {
            System.out.println("具体策略1的运算法则...");
        }
    
        @Override
        public String toString() {
            return "具体策略1";
        }
    }
    
    
    @Component
    public class ConcreteStrategy2 implements Strategy {
        @Override
        public void doSomething() {
            System.out.println("具体策略2的运算法则...");
        }
    
        @Override
        public String toString() {
            return "具体策略2";
        }
    }
    
    
    @Component
    public class DefaultStrategy implements Strategy {
        @Override
        public void doSomething() {
            System.out.println("默认策略的运算法则...");
        }
    
        @Override
        public String toString() {
            return "默认策略";
        }
    }
    
    

    2、实现工厂类

    @Component
    public class StrategyFactory {
        //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
        @Autowired
        private Map<String, Strategy> strategyMap;
    
        public Strategy getBy(String strategyName) {
            return strategyMap.get(strategyName);
        }
    }
    
    

    Spring会自动将Strategy接口的实现类注入到这个Map中(前提是实现类得是交给Spring 容器管理的),这个Map的key为bean id,可以用@Component(value = "xxx")的方式设置,如果直接用默认的方式的话,就是首字母小写。value值则为对应的策略实现类

    image.png

    测试类:

    @SpringBootTest
    class SpringbootDemoApplicationTests {
    
        @Autowired
        private ApplicationContext context;
    
        @Test
        public void test() {
            context.getBean(StrategyFactory.class).getBy("concreteStrategy1").doSomething();
            context.getBean(StrategyFactory.class).getBy("concreteStrategy2").doSomething();
        }
    
    }
    
    

    执行结果如下:

    具体策略1的运算法则...
    具体策略2的运算法则...
    
    

    3、别名转换

    上面测试类调用的使用使用的bean id,实际业务中应该是将传入的code转义成对应的策略类的bean id

    @Component
    @PropertySource("classpath:application.properties")
    @ConfigurationProperties(prefix = "strategy")
    public class StrategyAliasConfig {
        private HashMap<String, String> aliasMap;
    
        public static final String DEFAULT_STATEGY_NAME = "defaultStrategy";
    
        public HashMap<String, String> getAliasMap() {
            return aliasMap;
        }
    
        public void setAliasMap(HashMap<String, String> aliasMap) {
            this.aliasMap = aliasMap;
        }
    
        public String of(String entNum) {
            return aliasMap.get(entNum);
        }
    }
    
    

    配置文件application.properties

    strategy.aliasMap.strategy1=concreteStrategy1
    strategy.aliasMap.strategy2=concreteStrategy2
    
    
    @Component
    public class StrategyFactory {
        @Autowired
        private StrategyAliasConfig strategyAliasConfig;
    
        //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
        @Autowired
        private Map<String, Strategy> strategyMap;
    
        //找不到对应的策略类,使用默认的
        public Strategy getBy(String strategyName) {
            String name = strategyAliasConfig.of(strategyName);
            if (name == null) {
                return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
            }
            Strategy strategy = strategyMap.get(name);
            if (strategy == null) {
                return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
            }
            return strategy;
    
        }
    }
    
    

    测试类:

    @SpringBootTest
    class SpringbootDemoApplicationTests {
    
        @Autowired
        private ApplicationContext context;
    
        @Test
        public void test() {
            context.getBean(StrategyFactory.class).getBy("strategy1").doSomething();
            context.getBean(StrategyFactory.class).getBy("strategy2").doSomething();
        }
    
    }
    
    

    执行结果如下:

    具体策略1的运算法则...
    具体策略2的运算法则...
    

    相关文章

      网友评论

        本文标题:如何使用 Spring 实现策略模式+工厂模式

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