如果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)類即可。