美文网首页
Spring反射+策略模式替代switch/if-else

Spring反射+策略模式替代switch/if-else

作者: 那我懂你意思了_de16 | 来源:发表于2019-01-16 01:56 被阅读0次

    如果switch/if-else分支不固定,或将来有可能改,可以采用反射+策略模式来替换switch/if-else语句。例如动物,随着种类变化,我们需要不断增加switch分支,这样我们就可以使反射+策略模式,使之更加灵活。

    if-else方式:

    Animal animal = new Animal();
    if("dog".equals(type)) {
        animal = new Dog();
    } if else("cat".equals(type)) {
        animal = new Cat();
    }
    animal.eat();
    

    switch方式:

    Animal animal = new Animal();
    switch (type) {
        case "dog":
            animal  = new Dog();
            break;
        case "cat":
            animal  = new Cat();
            break;
    }
    animal.eat();
    

    Spring反射+策略模式:

    Animal接口(抽象策略角色):

    public interface Animal {
    
        void eat();
    }
    

    Cat实现Animal接口(具体实现策略):

    @Component
    public class Cat implements Animal {
    
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    

    Dog实现Animal接口(具体实现策略):

    @Component
    public class Dog implements Animal {
    
        @Override
        public void eat() {
            System.out.println("狗啃骨头");
        }
    }
    
    • @Component:将bean实例化交给spring容器管理。或者使用.xml配置文件<bean id="" class=""></bean>方式等等。

    AnimalFactory类(环境角色):

    @Service("animalFactory")
    public class AnimalFactory implements ApplicationContextAware, InitializingBean {
    
        private Map<String, Animal> animalMap;
    
        private ApplicationContext applicationContext;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            Map<String, Animal> animalMap = this.applicationContext.getBeansOfType(Animal.class);
    
            this.animalMap = animalMap;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
        public Animal getAnimal(String beanName) {
            return this.animalMap.get(beanName);
        }
    }
    
    • 由于AnimalFactory类实现ApplicationContextAware接口,Spring容器会在创建AnimalFactory类之后,自动调用实现接口的setApplicationContextAware()方法,调用该方法时,会将ApplicationContext(容器本身)作为参数传给该方法,我们可以在该方法中将Spring传入的参数ApplicationContext赋给AnimalFactory对象的applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身。
    • 实现InitializingBean接口,该接口提供了afterPropertiesSet方法。spirng容器在初始化bean的时候会执行afterPropertiesSet方法,我们可以在该方法中调用applicationContext接口提供的getBeansOfType方法获得实现Animal类的Bean,将之存储至map集合中。
    存储bean

    测试类:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DemoApplicationTests {
    
        @Autowired
        private AnimalFactory animalFactory;
    
        @Test
        public void test() {
            Animal animal = animalFactory.getAnimal("dog");
    //        Animal animal = animalFactory.getAnimal("cat");
            animal.eat();
        }
    
    }
    

    输出:

    狗啃骨头


    以后需求变更,只要增加实现类即可。

    相关文章

      网友评论

          本文标题:Spring反射+策略模式替代switch/if-else

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