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

如果switch/if-else分支不固定,或?qū)?lái)有可能改,可以采用反射+策略模式來(lái)替換switch/if-else語(yǔ)句。例如動(dòng)物,隨著種類變化,我們需要不斷增加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實(shí)現(xiàn)Animal接口(具體實(shí)現(xiàn)策略):

@Component
public class Cat implements Animal {

    @Override
    public void eat() {
        System.out.println("貓吃魚");
    }
}

Dog實(shí)現(xiàn)Animal接口(具體實(shí)現(xiàn)策略):

@Component
public class Dog implements Animal {

    @Override
    public void eat() {
        System.out.println("狗啃骨頭");
    }
}
  • @Component:將bean實(shí)例化交給spring容器管理。或者使用.xml配置文件<bean id="" class=""></bean>方式等等。

AnimalFactory類(環(huán)境角色):

@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類實(shí)現(xiàn)ApplicationContextAware接口,Spring容器會(huì)在創(chuàng)建AnimalFactory類之后,自動(dòng)調(diào)用實(shí)現(xiàn)接口的setApplicationContextAware()方法,調(diào)用該方法時(shí),會(huì)將ApplicationContext(容器本身)作為參數(shù)傳給該方法,我們可以在該方法中將Spring傳入的參數(shù)ApplicationContext賦給AnimalFactory對(duì)象的applicationContext實(shí)例變量,因此接下來(lái)可以通過(guò)該applicationContext實(shí)例變量來(lái)訪問(wèn)容器本身。
  • 實(shí)現(xiàn)InitializingBean接口,該接口提供了afterPropertiesSet方法。spirng容器在初始化bean的時(shí)候會(huì)執(zhí)行afterPropertiesSet方法,我們可以在該方法中調(diào)用applicationContext接口提供的getBeansOfType方法獲得實(shí)現(xiàn)Animal類的Bean,將之存儲(chǔ)至map集合中。
存儲(chǔ)bean

測(cè)試類:

@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();
    }

}

輸出:

狗啃骨頭


以后需求變更,只要增加實(shí)現(xiàn)類即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容