如果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();
}
}
輸出:
狗啃骨頭
以后需求變更,只要增加實現類即可。