引入
以前在编码中,遇到过下面的情况,根据设备类型,调用不同的Converter转换类。最初代码如下:
if(type1){
convert1();
}
else if(type2){
convert2();
}
else if(type3){
convert3();
}
如果增加类型,需要修改代码,增加if else逻辑。我当时感觉代码ugly,所以用了一个map,映射设备类型和converter类。应用层代码如下:
Converter converter=map.get(type);
converter.converte()
所有设备类型转换类都实现Converter接口。这样代码简洁很多。但是问题没有解决,增加type类型,还需要修改我的map代码,往map添加记录。有没有其他方法呢?根据设计模式,代码应该是对扩展开发,对修改关闭的。我的思路应用了策略模式,但是不够完美。
优化设计
优化是如何不维护map的映射关系?期待的是增加设备类型的converter之后,自动能够进行转换。
1. 新建converter类,实现converter接口。converter类增加一个注解,注解的值是设备类型。
2 启动的时候,获取实现converter接口的所有类,利用annoatation和类,动态生成我们的map结构
3调用方法
Converter convert=ConverterContext.getConverter(Enum.DMA);
converter.converter();
代码
package com.puhui.shoppingmallloan.web.controller;
import com.sun.xml.internal.ws.handler.ServerLogicalHandlerTube;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
/**
* 2 * @Author: kerry
* 3 * @Date: 2019/2/27 13:37
* 4
*/
@Service
public class ConverterContext implements ApplicationRunner {
@Autowired
private ApplicationContext applicationContext;
private static Map<String,Converter> map=new HashMap<>();
@Override
public void run(ApplicationArguments sce) {
Map<String, Converter> allClasses = applicationContext.getBeansOfType(Converter.class);
for(Map.Entry entry:allClasses.entrySet()){
Converter converter=(Converter) entry.getValue();
DeviceType annotation=applicationContext.findAnnotationOnBean((String) entry.getKey(),DeviceType.class);
map.put(annotation.type(),converter);
}
}
public static Converter getConverter(TypeEnum typeEnum){
return map.get(typeEnum);
}
}
package com.puhui.shoppingmallloan.web.controller;
import java.lang.annotation.*;
/**
* 2 * @Author: kerry
* 3 * @Date: 2019/2/27 13:28
* 4
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DeviceType {
String type() default "";
}
package com.puhui.shoppingmallloan.web.controller;
import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
/**
* 2 * @Author: kerry
* 3 * @Date: 2019/2/27 13:28
* 4
*/
@DeviceType(type ="DMA")
@Service
public class DMAConverter implements Converter {
@Override
public void converter() {
}
}
package com.puhui.shoppingmallloan.web.controller;
/**
* 2 * @Author: kerry
* 3 * @Date: 2019/2/27 13:30
* 4
*/
public enum TypeEnum {
DMA("DMA"),XMA("XMA"),MCU("MCU");
private String code;
private TypeEnum(String code) {
this.code = code;
}
public String getCode() {
return code;
}
@Override
public String toString() {
return this.code;
}
}