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

文章目录

  • 概述
  • 原工程缩影
  • 第一次优化 【使用多态代替判断条件】
    • Step1: 定义一个抽象的父类 AbstractFlowInfoExecutor ,抽取公共属性和方法
    • Step2: 子类重写父类的方法,实现自定义业务逻辑
    • Step3: 改造Service层
    • Step3: 测试下
  • 第二次优化【工厂模式】
    • Step1:使用工厂模式,定义一个工厂类来生成不用的子类Executor
    • Step2: Service层继续改造
    • Step3: 测试下
  • 小结

概述

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

工程中有段代码如下:
Java-记一次if-else代码优化_第1张图片

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

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


原工程缩影

越简单 越直观 ,工程如下:
Java-记一次if-else代码优化_第2张图片

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);
	}
}

Java-记一次if-else代码优化_第3张图片


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

Java-记一次if-else代码优化_第4张图片

既然有了上面的分析:

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

来,操刀吧

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: 测试下

Java-记一次if-else代码优化_第5张图片


第二次优化【工厂模式】

Java-记一次if-else代码优化_第6张图片

经过上一轮的优化后,虽然把业务逻辑抽取到单独的子类中了,但Service层依然还是存在分支条件
Java-记一次if-else代码优化_第7张图片
那继续优化吧

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: 测试下

Java-记一次if-else代码优化_第8张图片


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

Java-记一次if-else代码优化_第9张图片
结果:
Java-记一次if-else代码优化_第10张图片


Enum也是可以的

Java-记一次if-else代码优化_第11张图片

Java-记一次if-else代码优化_第12张图片

结果:
Java-记一次if-else代码优化_第13张图片


小结

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

你可能感兴趣的:(【Java,-Java,Base】)