最近在项目开发中,发现之前的代码里面if else 实在用的太多,大段大段的判断条件,趁着疫情不能上班,在此优化了下代码,分享下自己的经验,切入正题,搞起:
1. 修改之前代码:
if(CommonEnum.CARINFO_KAOCAR_TRAG_07.getCode().equals(operateCode)){
dosomethingA();
}else if (CommonEnum.CARINFO_SEND_02.getCode().equals(operateCode) || CommonEnum.CARINFO_LEFT_04.getCode().equals(operateCode)) {
dosomethingB();
}else if(CommonEnum.CARINFO_ARRVIE_03.getCode().equals(operateCode)||
CommonEnum.CARINFO_ARRVIE_TRAG_05.getCode().equals(operateCode)) {
dosomethingC();
}
ps : 将实际的业务代码处理了下。
2. 用策略模式(具体详细原理自己可以百度下)优化代码
2.1先定一个处理车辆kfk 消息接口,专门处理消息方法
public interface TransitCodeKfkService {
void handleMessage(CarInfoDto dto);
}
2.2 定义具体处理对应相关的操作码实体类,继承子上面接口
@Service
@TransitCodeTypeHandler(value = CarFvpEnum.CARINFO_ARRVIE_303)
public class TransitCode303kfkServiceImpl extends TransitCodeKfkService {
@Override
public void handleMessage(CarInfoDto dto) {
doSomeThings(dto);
}
这个类主要处理对应相关操作码相关逻辑。
可能大多数人可能会想到要需要如下一个Map, Map<操作码,kafka消息处理对象>,这样直接根据消息类型就能拿到消息处理对象,调用消息处理对象的方法即可。我们就是这样做的,但是我们不想手动维护这个Map对象,因为每次增加新的消息处理类,Map的初始化过程就得修改。
我们使用了注解+ApplicationListener来保存这种映射关系,来看看怎么做的把
2.3定义一个操作码消息类型的枚举类
public enum CarFvpEnum {
STOP_DEPARTURE("01","A类"),
CARINFO_SEND_02("02","B类"),
CARINFO_ARRVIE_03("03","C类"),
CARINFO_ARRVIE_TRAG_05("05","D类"),
CARINFO_KAOCAR_TRAG_07("07","E类");
private CarFvpEnum( String carStatus, String desc) {
this.carFvp =carStatus;
this.desc =desc;
}
public String getCarFvp() {
return carFvp;
}
public String carFvp;
public String getDesc() {
return desc;
}
public String desc;
// 覆盖方法
@Override
public String toString() {
return this.carFvp +"_"+this.desc;
}
}
2.4定义一个注解
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TransitCodeTypeHandler {
CarFvpEnum value();
}
2.5 用一个context对象保存了消息类型->消息处理对象的映射关系
@Component
public class TransitCodKfkServiceContext {
private final Map handleCodeMap = new HashMap <>();
public TransitCodeKfkService getTransitCodeKfkService(String code) {
return handleCodeMap.get(code);
}
public void setTransitCodeKfkService(String code, TransitCodeKfkService service) {
handleCodeMap.put(code, service);
}
2.6 最精彩的地方出现了,
@Component
public class TransitKfkServiceListener implements ApplicationListener {
/**
* Handle an application event.
*
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map beans = event.getApplicationContext().getBeansWithAnnotation(TransitCodeTypeHandler.class);
TransitCodKfkServiceContext messageServiceContext = event.getApplicationContext().getBean(TransitCodKfkServiceContext.class);
beans.forEach((name, bean) -> {
TransitCodeTypeHandler typeHandler = bean.getClass().getAnnotation(TransitCodeTypeHandler.class);
messageServiceContext.setTransitCodeKfkService(typeHandler.value().carFvp, (TransitCodeKfkService) bean);
});
}
}
在spring的启动过程中,通过解析注解,将操作码类型->消息处理对象的映射关系保存到TransitCodKfkServiceContext对象中。
2.7 具体使用:
@Autowired
private TransitCodKfkServiceContext transitCodeKfkServiceContxt;
TransitCodeKfkService transitCodeKfkService=
transitCodeKfkServiceContxt.getTransitCodeKfkService(dto.getOperateCode());
transitCodeKfkService.handleMessage(dto);
总结:除了通过 将操作码类型->消息处理对象的映射关系保存到TransitCodKfkServiceContext对象中,还有那些方式能put 到map 中呢?