Java-记一次if-else代码优化

简介: Java-记一次if-else代码优化

概述

我们这里来说因多种状态引起的多个分支判断条件的代码的优化

工程中有段代码如下:

2019013014444920.png

可以看到,分支条件已经到了9个,在Service层直接调用了持久层(Mybatis)提供的接口,也还算清晰。不过代码量太大,增加个状态就要修改这个类,难以维护。 那么我们该如何优化呢? 核心思想:使用多态代替判断条件

为了更加清晰,下面新建个单独的工程来演示下,并逐步优化


原工程缩影


越简单 越直观 ,工程如下:

2019013014532053.png

Domain对象

package com.artisan.optimization.ifelse;
public class FlowInfo {
    private Integer currentState;
    // 其他字段省略....
  public Integer getCurrentState() {
    return currentState;
  }
  public void setCurrentState(Integer currentState) {
    this.currentState = currentState;
  }
}


持久层

package com.artisan.optimization.ifelse;
import java.util.ArrayList;
import java.util.List;
public class FlowInfoDao {
  List<FlowInfo> flowInfoList = new ArrayList<>();
  public List<FlowInfo> getWorkDraftList(FlowInfo flowInfo) {
    System.out.println("draft....");
    return flowInfoList;
  }
  public List<FlowInfo> getWorkTodoList(FlowInfo flowInfo) {
    System.out.println("todo....");
    return flowInfoList;
  }
  public List<FlowInfo> getWorkFinishList(FlowInfo flowInfo) {
    System.out.println("finish....");
    return null;
  }
  public List<FlowInfo> getWorkRejectList(FlowInfo flowInfo) {
    System.out.println("reject....");
    return null;
  }
}


Service层

package com.artisan.optimization.ifelse;
import java.util.List;
public class FlowInfoService {
  FlowInfoDao flowDao = new FlowInfoDao();
  public List<FlowInfo> getWorkFlowList(final FlowInfo flowInfo) {
    // 0:草稿
    if (0 == flowInfo.getCurrentState()) {
      return flowDao.getWorkDraftList(flowInfo);
    }
    // 1:待办
    if (1 == flowInfo.getCurrentState()) {
      return flowDao.getWorkTodoList(flowInfo);
    }
    // 2:完成
    if (2 == flowInfo.getCurrentState()) {
      return flowDao.getWorkFinishList(flowInfo);
    }
    // 3:驳回
    if (3 == flowInfo.getCurrentState()) {
      return flowDao.getWorkRejectList(flowInfo);
    }
    return null;
  }
}


模拟的原始代码如上, 这里我们暂定有4个状态,假设有很多个,难以维护。

分析下上面的代码在不同判断条件下,执行的业务逻辑是不同的,那么我们可以把这种执行逻辑抽象出来,用多态的形式来定义不同的执行方式。


测试

package com.artisan.optimization.ifelse;
public class Main {
  public static void main(String[] args) {
    FlowInfoService flowInfoService  = new FlowInfoService();
    FlowInfo flowInfo = new FlowInfo();
    flowInfo.setCurrentState(0);
    flowInfoService.getWorkFlowList(flowInfo);
    flowInfo.setCurrentState(1);
    flowInfoService.getWorkFlowList(flowInfo);
    flowInfo.setCurrentState(2);
    flowInfoService.getWorkFlowList(flowInfo);
    flowInfo.setCurrentState(3);
    flowInfoService.getWorkFlowList(flowInfo);
  }
}

20190130145949585.png


第一次优化 【使用多态代替判断条件】


2019013014535570.png

既然有了上面的分析:

分析下上面的代码在不同判断条件下,执行的业务逻辑是不同的,那么我们可以把这种执行逻辑抽象出来,用多态的形式来定义不同的执行方式。

来,操刀吧


Step1: 定义一个抽象的父类 AbstractFlowInfoExecutor ,抽取公共属性和方法

package com.artisan.optimization.ifelse.executor;
import java.util.List;
import com.artisan.optimization.ifelse.FlowInfo;
import com.artisan.optimization.ifelse.FlowInfoDao;
public abstract class AbstractFlowInfoExecutor {
  // 公共属性,提取到抽象类中,子类直接使用即可
  FlowInfoDao flowDao = new FlowInfoDao();
  // 子类可重写该方法
  public List<FlowInfo> process(FlowInfo flowInfo) {
    return null;
  }
}


Step2: 子类重写父类的方法,实现自定义业务逻辑


完成了抽象父类的定义后,就可以把代码块中不同条件下的方法抽到各个不同的具体类里面去了,如下


flowInfo.getCurrentState() == 0 分支

package com.artisan.optimization.ifelse.executor;
import java.util.List;
import com.artisan.optimization.ifelse.FlowInfo;
public class DraftExecutor extends AbstractFlowInfoExecutor {
  @Override
  public List<FlowInfo> process(FlowInfo flowInfo) {
    return flowDao.getWorkDraftList(flowInfo);
  }
}

flowInfo.getCurrentState() == 1 分支

package com.artisan.optimization.ifelse.executor;
import java.util.List;
import com.artisan.optimization.ifelse.FlowInfo;
public class TodoExecutor extends AbstractFlowInfoExecutor {
  @Override
  public List<FlowInfo> process(FlowInfo flowInfo) {
    return flowDao.getWorkTodoList(flowInfo);
  }
}

flowInfo.getCurrentState() == 2 分支

package com.artisan.optimization.ifelse.executor;
import java.util.List;
import com.artisan.optimization.ifelse.FlowInfo;
public class FinishExecutor extends AbstractFlowInfoExecutor {
  @Override
  public List<FlowInfo> process(FlowInfo flowInfo) {
    return flowDao.getWorkFinishList(flowInfo);
  }
}


flowInfo.getCurrentState() == 3 分支

package com.artisan.optimization.ifelse.executor;
import java.util.List;
import com.artisan.optimization.ifelse.FlowInfo;
public class RejectExecutor extends AbstractFlowInfoExecutor {
  @Override
  public List<FlowInfo> process(FlowInfo flowInfo) {
    return flowDao.getWorkRejectList(flowInfo);
  }
}


Step3: 改造Service层

package com.artisan.optimization.ifelse;
import java.util.List;
import com.artisan.optimization.ifelse.executor.AbstractFlowInfoExecutor;
import com.artisan.optimization.ifelse.executor.DraftExecutor;
import com.artisan.optimization.ifelse.executor.FinishExecutor;
import com.artisan.optimization.ifelse.executor.RejectExecutor;
import com.artisan.optimization.ifelse.executor.TodoExecutor;
public class FlowInfoService {
  public List<FlowInfo> getWorkFlowList(final FlowInfo flowInfo) {
    AbstractFlowInfoExecutor executor = null;
    // 根据状态实例化不同的executor
    // 0:草稿
    if (0 == flowInfo.getCurrentState()) {
      executor = new DraftExecutor();
    }
    // 1:待办
    if (1 == flowInfo.getCurrentState()) {
      executor = new TodoExecutor();
    }
    // 2:完成
    if (2 == flowInfo.getCurrentState()) {
      executor = new FinishExecutor();
    }
    // 3:驳回
    if (3 == flowInfo.getCurrentState()) {
      executor = new RejectExecutor();
    }
    // 执行
    return executor.process(flowInfo);
  }
}


Step3: 测试下


20190130152825549.png

第二次优化【工厂模式】


20190130145403290.png

经过上一轮的优化后,虽然把业务逻辑抽取到单独的子类中了,但Service层依然还是存在分支条件


20190130152233714.png

那继续优化吧

Step1:使用工厂模式,定义一个工厂类来生成不用的子类Executor

package com.artisan.optimization.ifelse.factory;
import com.artisan.optimization.ifelse.FlowInfo;
import com.artisan.optimization.ifelse.executor.AbstractFlowInfoExecutor;
import com.artisan.optimization.ifelse.executor.DraftExecutor;
import com.artisan.optimization.ifelse.executor.FinishExecutor;
import com.artisan.optimization.ifelse.executor.RejectExecutor;
import com.artisan.optimization.ifelse.executor.TodoExecutor;
public class FlowInfoExecutorFactory {
  public static AbstractFlowInfoExecutor executor(FlowInfo flowInfo) {
    // 
    if (0 == flowInfo.getCurrentState()) {
      return  new DraftExecutor();
    }
    // 1:待办
    if (1 == flowInfo.getCurrentState()) {
      return new TodoExecutor();
    }
    // 2:完成
    if (2 == flowInfo.getCurrentState()) {
      return new FinishExecutor();
    }
    // 3:驳回
    if (3 == flowInfo.getCurrentState()) {
      return new RejectExecutor();
    }
    return null;
  }
}

Step2: Service层继续改造

package com.artisan.optimization.ifelse;
import java.util.List;
import com.artisan.optimization.ifelse.executor.AbstractFlowInfoExecutor;
import com.artisan.optimization.ifelse.factory.FlowInfoExecutorFactory;
public class FlowInfoService {
  public List<FlowInfo> getWorkFlowList(final FlowInfo flowInfo) {
    // 工厂
    AbstractFlowInfoExecutor executor = FlowInfoExecutorFactory.executor(flowInfo);
    return executor.process(flowInfo);
  }
}


2行,搞定!

Step3: 测试下


20190130152727462.png

当然了,工厂中状态和Executor的映射关系可以使用Map来维护


20190305191535548.png

结果:


20190305191757516.png

Enum也是可以的


2019030519163924.png


20190305191659445.png

结果:


20190305191725362.png


小结


经过**多态和工厂模式**的改造后,只需要两行就可以了。 各个子类Executor和Service层的耦合已经很低了,如果有新的状态,只需要修改工厂类和增加子Executor即可。

相关文章
|
1月前
|
人工智能 IDE Java
CodeFuse代码优化实战:Java日期格式化时如何正确表示年份?
Java日期格式化时这里的坑你知道吗?一起来看正确用法!使用 CodeFuse 代码优化功能,可以帮你完美避坑,快来试试吧~
27 0
|
5月前
|
安全 Java API
Java编程技巧:if-else优化实践总结归纳
说实话,其实我很讨厌在代码里大量使用if-else,一是因为该类代码执行方式属于面向过程的,二嘛,则是会显得代码过于冗余。这篇笔记,主要记录一些自己在工作实践当中针对if-else的优化心得,将会不定期地长期更新。
64 0
|
8月前
|
网络协议 Java
Java实现TCP通信的文件上传 之 代码优化开启多线程
Java实现TCP通信的文件上传 之 代码优化开启多线程
|
4月前
|
Java 网络安全 调度
谈谈代码:Java IO业务代码优化之路
前阵子休息天日常在寻找项目里不好的代码,看到了这样的一段代码...
39 1
|
7月前
JAVA_if-else if-else多选择结构
JAVA_if-else if-else多选择结构
36 0
|
9月前
|
SQL 存储 算法
JAVA代码优化,接口优化,SQL优化 (小技巧)(七)
JAVA代码优化,接口优化,SQL优化 (小技巧)(七)
174 0
|
9月前
|
SQL Java 数据库
JAVA代码优化,接口优化,SQL优化 (小技巧)(六)
JAVA代码优化,接口优化,SQL优化 (小技巧)(六)
99 0
|
9月前
|
SQL 缓存 监控
JAVA代码优化,接口优化,SQL优化 (小技巧)(五)
JAVA代码优化,接口优化,SQL优化 (小技巧)(五)
93 0
|
9月前
|
SQL 缓存 NoSQL
JAVA代码优化,接口优化,SQL优化 (小技巧)(四)
JAVA代码优化,接口优化,SQL优化 (小技巧)(四)
173 0
|
9月前
|
SQL 存储 监控
JAVA代码优化,接口优化,SQL优化 (小技巧)(三)
JAVA代码优化,接口优化,SQL优化 (小技巧)(三)
108 0