设计模式之美,简洁代码之践 ----- 策略模式解决过多if else 繁琐问题

      最近在项目开发中,发现之前的代码里面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 中呢?

 

 

你可能感兴趣的:(设计模式)