记使用设计模式解决大量ifelse的问题
本文主要以spring + 策略 + 工厂模式来进行演示
大家好,继昨天的策略+工厂模式解决ifelse的问题后,今天我们再来加一种框架来看看。
spring框架作为一个超级牛逼的框架我相信在座的各位应该没有不用的吧[狗头],那么我们该怎么在spring框架中应用策略+工厂模式呢,话不多说直接上手!!
咱先来创建一个springboot项目[嘿嘿]
启动类做起来
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DesignpatternsApplication {
public static void main(String[] args) {
SpringApplication.run(DesignpatternsApplication.class, args);
}
}
继续将昨天的策略接口,业务类和枚举类搬过来。。
枚举类就不用动了
public enum Role {
bussiness("Bussiness"),
collection("Collection"),
productino("Production");
private String hotelCode;
//将三个值加载进list集合
public static List<String> getList() {
return Arrays.asList(Role.values()).stream()
.map(Role::getHotelCode)
.collect(Collectors.toList());
}
Role(String hotelCode) {
this.hotelCode = hotelCode;
}
public String getHotelCode() {
return hotelCode;
}
}
然后再把策略接口也拿过来
public interface getContactService {
List<ZsBcContractDate> list(ZsBcContractDate zsBcContractDate);
}
好,再到业务类了,这就要有一些改变了,我们要将他们交给spring容器进行管理
@Component("BussinessContactServiceImpl")
public class BussinessContactServiceImpl implements getContactService {
@Override
public List<ZsBcContractDate> list(ZsBcContractDate zsBcContractDate) {
return initContact(zsBcContractDate);
}
private List<ZsBcContractDate> initContact(ZsBcContractDate zsBcContractDate) {
return new ArrayList<ZsBcContractDate>() {
{
add(new ZsBcContractDate(1L));
add(new ZsBcContractDate(2L));
add(new ZsBcContractDate(3L));
}
};
}
}
@Component("CollectionContactServiceImpl")
public class CollectionContactServiceImpl implements getContactService {
@Override
public List<ZsBcContractDate> list(ZsBcContractDate zsBcContractDate) {
return initContact(zsBcContractDate);
}
private List<ZsBcContractDate> initContact(ZsBcContractDate zsBcContractDate) {
return new ArrayList<ZsBcContractDate>() {
{
add(new ZsBcContractDate(4L));
add(new ZsBcContractDate(5L));
add(new ZsBcContractDate(6L));
}
};
}
}
@Component("ProductionContactServiceImpl")
public class ProductionContactServiceImpl implements getContactService {
@Override
public List<ZsBcContractDate> list(ZsBcContractDate zsBcContractDate) {
return initContact(zsBcContractDate);
}
private List<ZsBcContractDate> initContact(ZsBcContractDate zsBcContractDate) {
return new ArrayList<ZsBcContractDate>() {
{
add(new ZsBcContractDate(7L));
add(new ZsBcContractDate(8L));
add(new ZsBcContractDate(9L));
}
};
}
}
接下来就来到我们最重要的工厂类了!!
这里我采用了applicationContext.getBeansOfType(getContactService.class);直接从容器中获取实现了这个接口的所有子类,所以说我们在上面说了要将所有的业务类交给spring容器进行管理。
@Component
public class ContactSpringFactory {
/**
* 服务实现后缀
*/
private static final String CONTACT_SERVICE_SUFFIX = "ContactServiceImpl";
private static Map<String, getContactService> CONTACT_SERVER_MAP;
@Autowired
private ApplicationContext applicationContext;
public ContactSpringFactory() {
init();
}
public static getContactService getContactServiceImpl(String hotelCode) {
return CONTACT_SERVER_MAP.get(hotelCode + CONTACT_SERVICE_SUFFIX);
}
private void init(){
CONTACT_SERVER_MAP = applicationContext.getBeansOfType(getContactService.class);
}
}
搞一个controller准备启动了[旺柴]
@RestController
@RequestMapping("/test")
public class Demo01 {
@GetMapping("/getCode")
public void main(String code) {
getContactService bussiness = ContactSpringFactory.getContactServiceImpl(code);
ZsBcContractDate zsBcContractDate = new ZsBcContractDate(1L);
List<ZsBcContractDate> list = bussiness.list(zsBcContractDate);
System.out.println(list);
}
}
启动gogo ????空指针
Caused by: java.lang.NullPointerException: null
at com.example.designpatterns.Factory.ContactSpringFactory.init(ContactSpringFactory.java:40) ~[classes/:na]
at com.example.designpatterns.Factory.ContactSpringFactory.<init>(ContactSpringFactory.java:32) ~[classes/:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_40]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_40]
at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_40]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.11.RELEASE.jar:5.2.11.RELEASE]
... 26 common frames omitted
人都惊呆了!!百思不得其解。。。。。
看了一下日志,在工厂类的初始化方法中爆出来的,原来是applicationContext为null,所以没有值能取出来。当时我就想,咦我不是加了@Autowired吗 ,为什么没有注入进去,百度搜了下看到了一个差不多忘了干干净净的东西了 ‘构造注入’。。
CONTACT_SERVER_MAP = applicationContext.getBeansOfType(getContactService.class);
@Component
public class ContactSpringFactory {
/**
* 服务实现后缀
*/
private static final String CONTACT_SERVICE_SUFFIX = "ContactServiceImpl";
private static Map<String, getContactService> CONTACT_SERVER_MAP;
private ApplicationContext applicationContext;
public ContactSpringFactory(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
init();
}
public static getContactService getContactServiceImpl(String hotelCode) {
return CONTACT_SERVER_MAP.get(hotelCode + CONTACT_SERVICE_SUFFIX);
}
private void init(){
CONTACT_SERVER_MAP = applicationContext.getBeansOfType(getContactService.class);
}
}
用postman测试http://localhost:8080/test/getCode?code=Bussiness
这样,在他注入后我们在进行map的初始化,这样就不会爆空指针啦,项目就能正确的跑起来啦!
如有错误,欢迎大佬指出[拜拜]