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即可。

相关文章
|
2月前
|
Java 程序员 编译器
在Java编程中,if-else与switch语句犹如武林高手的剑与刀
【10月更文挑战第3天】在Java编程中,if-else与switch语句犹如武林高手的剑与刀。本文通过示例展示如何巧妙运用这两种工具,提升代码效率与可读性。从精简if-else结构到高效使用switch语句,再到性能考量,帮助你在不同场景下做出最佳选择,让你的程序更加流畅高效。掌握这些技巧,你将在Java世界中游刃有余!
25 2
|
4月前
|
Java C++ 开发者
if-else VS switch:谁才是Java条件判断的王者?
if-else VS switch:谁才是Java条件判断的王者?
46 3
|
4月前
|
运维 Java 程序员
新手进阶:用对if-else,让你的Java逻辑判断不再纠结!
新手进阶:用对if-else,让你的Java逻辑判断不再纠结!
78 3
|
4月前
|
Java 程序员 编译器
Java高手教你如何灵活运用if-else和switch,提升代码效率!
在Java编程中,if-else与switch语句犹如剑与刀,恰当地使用能让你的代码战无不胜。本文通过示例展示如何精简if-else结构,利用Map提高权限分配系统的可读性和维护性;如何高效运用switch语句处理订单状态,使代码更清晰;并探讨了两者在不同场景下的性能考量。掌握这些技巧,你将在Java编程的世界里游刃有余,成就非凡!
41 3
|
4月前
|
Java 开发者
超实用!一文搞懂Java中if-else和switch的正确打开方式!
超实用!一文搞懂Java中if-else和switch的正确打开方式!
62 2
|
4月前
|
Java 开发者
别再傻傻分不清!Java if-else与switch的性能对比全解析!
别再傻傻分不清!Java if-else与switch的性能对比全解析!
67 1
|
4月前
|
Java
Java条件语句:if-else与switch的适用场景大起底
Java条件语句:if-else与switch的适用场景大起底
121 2
|
4月前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
62 2
|
4月前
|
Java 开发者
在Java编程的广阔天地中,if-else与switch语句犹如两位老练的舵手,引领着代码的流向,决定着程序的走向。
在Java编程中,if-else与switch语句是条件判断的两大利器。本文通过丰富的示例,深入浅出地解析两者的特点与应用场景。if-else适用于逻辑复杂的判断,而switch则在处理固定选项或多分支选择时更为高效。从逻辑复杂度、可读性到性能考量,我们将帮助你掌握何时选用哪种语句,让你在编程时更加得心应手。无论面对何种挑战,都能找到最适合的解决方案。
41 1
|
4月前
|
设计模式 算法 Java
Java中的if-else if-else语句
Java中的if-else if-else语句