如果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
集合中。
测试类:
@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();
}
}
输出:
狗啃骨头
以后需求变更,只要增加实现类即可。
网友评论