Hello!小伙伴们,你们的业务代码中是否经常遇到这样的代码,是不是惨不忍睹
下面看一下实际的场景
获取验机接口接口,验机项有几十项
外观字段:清洁程度、警示灯、轮胎、栏杆锁销、篮筐
功能字段:叉车:刹车释放功能、平台延伸功能、急停开关、刹车、升降动作;臂车:各部位润滑、急停开关、刹车、升降动作、发动机
/**
* 获取外观验机结果
*
* @param check 验机结果
* @param res 返回值
*/
private void getFacadeCheckResult(CheckPo check, QueryDeviceCheckResponse res) {
res.setFacade(DeviceEnum.CheckItemResult.NORMAL.getState());
if (check.getCleanLevelIsNorm() == 0) {
res.setFacade(0);
} else if (check.getWarnLightIsNorm() == 0) {
res.setFacade(0);
} else if (check.getTireIsNorm() == 0) {
res.setFacade(0);
} else if (check.getRailingLockingPinIsNorm() == 0) {
res.setFacade(0);
} else if (check.getBasketOutIsShape() == 0) {
res.setFacade(0);
}
}
/**
* 获取功能验机结果
*
* @param check 验机结果
* @param res 返回值
*/
private void getForkFunctionCheckResult(CheckPo check, QueryDeviceCheckResponse res) {
res.setFunction(DeviceEnum.CheckItemResult.NORMAL.getState());
if (DeviceEnum.DeviceType.FORK.name().equalsIgnoreCase(res.getDeviceType())) {
if (check.getBrakeReleaseIsNorm() == DeviceEnum.CheckItemResult.ABNORMAL.getState()) {
res.setFunction(DeviceEnum.CheckItemResult.ABNORMAL.getState());
} else if (check.getPlatformExtensionIsNorm() == DeviceEnum.CheckItemResult.ABNORMAL.getState()) {
res.setFunction(DeviceEnum.CheckItemResult.ABNORMAL.getState());
} else if (check.getEmergencySwitchIsNorm() == DeviceEnum.CheckItemResult.ABNORMAL.getState()) {
res.setFunction(DeviceEnum.CheckItemResult.ABNORMAL.getState());
} else if (check.getBrakeIsNorm() == DeviceEnum.CheckItemResult.ABNORMAL.getState()) {
res.setFunction(DeviceEnum.CheckItemResult.ABNORMAL.getState());
} else if (check.getLiftingIsNorm() == DeviceEnum.CheckItemResult.ABNORMAL.getState()) {
res.setFunction(DeviceEnum.CheckItemResult.ABNORMAL.getState());
}
}
if (getCheckItemResult(check, FORK_FUNCTION_CHECK_FIELD)) {
res.setFacade(DeviceEnum.CheckItemResult.ABNORMAL.getState());
}
}
/**
* 获取外功能机结果
*
* @param check 验机结果
* @param res 返回值
*/
private void getArmOrCurvedFunctionCheckResult(CheckPo check, QueryDeviceCheckResponse res) {
res.setFunction(DeviceEnum.CheckItemResult.NORMAL.getState());
if (DeviceEnum.DeviceType.ARM.name().equalsIgnoreCase(res.getDeviceType())
|| DeviceEnum.DeviceType.CURVED.name().equalsIgnoreCase(res.getDeviceType())) {
if (check.getLubricationPartsIsNorm() == 0) {
res.setFunction(1);
}
else if (check.getEmergencySwitchIsNorm() == 0) {
res.setFunction(1);
}
else if (check.getBrakeIsNorm() == 0) {
res.setFunction(1);
}
else if (check.getLiftingIsNorm() == 0) {
res.setFunction(1);
}
if (check.getIsEngine() == 1) {
if (check.getCoolantIsNorm() == 0) {
res.setFunction(0);
} else if (check.getOilLevelIsNorm() == 0) {
res.setFunction(0);
} else if (check.getAirFilterIsNorm() == 0) {
res.setFunction(0);
} else if (check.getEngineBeltIsNorm() == 0) {
res.setFunction(0);
} else if (check.getEngineOilPortIsNorm() == 0) {
res.setFunction(0);
} else if (check.getWaterSeparatorIsNorm() == 0) {
res.setFunction(0);
}
}
}
}
通过反射优化后
/**
* 外观字段:清洁程度、警示灯、轮胎、栏杆锁销、篮筐
*/
private static final List<String> FACADE_CHECK_FIELD = new ArrayList<>();
static {
FACADE_CHECK_FIELD.add("cleanLevelIsNorm");
FACADE_CHECK_FIELD.add("warnLightIsNorm");
FACADE_CHECK_FIELD.add("tireIsNorm");
FACADE_CHECK_FIELD.add("railingLockingPinIsNorm");
FACADE_CHECK_FIELD.add("basketOutIsShape");
}
/**
* 功能字段:叉车:刹车释放功能、平台延伸功能、急停开关、刹车、升降动作;
*/
private static final List<String> FORK_FUNCTION_CHECK_FIELD = new ArrayList<>();
static {
FORK_FUNCTION_CHECK_FIELD.add("brakeReleaseIsNorm");
FORK_FUNCTION_CHECK_FIELD.add("platformExtensionIsNorm");
FORK_FUNCTION_CHECK_FIELD.add("emergencySwitchIsNorm");
FORK_FUNCTION_CHECK_FIELD.add("brakeIsNorm");
FORK_FUNCTION_CHECK_FIELD.add("liftingIsNorm");
}
/**
* 功能字段:臂车:各部位润滑、急停开关、刹车、升降动作、发动机
*/
private static final List<String> ARM_OR_CURVED_FUNCTION_CHECK_FIELD = new ArrayList<>();
static {
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("lubricationPartsIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("emergencySwitchIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("brakeIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("liftingIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("coolantIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("oilLevelIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("airFilterIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("engineBeltIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("engineOilPortIsNorm");
ARM_OR_CURVED_FUNCTION_CHECK_FIELD.add("waterSeparatorIsNorm");
}
/**
* 获取验机项结果
*
* @param check 验机结果
* @param fieldNames 检查项字段集合
*/
private boolean getCheckItemResult(CheckPo check, List<String> fieldNames) {
Field[] fields = CheckPo.class.getDeclaredFields();
for (Field f : fields) {
try {
for (String fieldName : fieldNames) {
if (f.getName().equals(fieldName)) {
f.setAccessible(true);
if (f.get(check) instanceof Integer) {
Integer result = (Integer) f.get(check);
// 有异常
if (result == 0) {
return true;
}
}
}
}
} catch (IllegalAccessException e) {
log.error("getCheckItemResult exception ", e);
}
}
return false;
}
代码有以下几个问题
1、代码不整洁,可读性差
2、代码不容易维护
3、代码扫描不过,圈复杂度太高
今天我想来总结一下这样的if-else-if 怎样优化
其实最先想到的就是封装+卫语句
封装就是把if中分散的凌乱的代码封装成一个方法,卫语句就是把复杂的的条件表达式拆分成多个条件表达式,条件为真时立刻从方法体中返回。优化后代码大概张这个样子
if(condition) {
doSth1();
return;
}
if(condition) {
doSth2();
return;
}
if(condition) {
doSth3();
return;
}
、、
return;
有点Java思想的人的就会利用多态了,你也可以说是工厂模式或者策略模式等,本质上都是多态的运用,优化后的代码长大概张这个样子
private TravelStrategy strategy;
public TravelStrategy travel (String type){
if ("TRAIN".equals(type)){
strategy = new StrategyTrain();
} else if ("BUS".equals(type)){
strategy = new StrategyBus();
} else if ("HIGHTRAIN".equals(type)){
strategy = new StrategyHighTrain();
} else if ("CAR".equals(type)){
strategy = new StrategyCar();
} else if ("METRO".equals(type)){
strategy = new StrategyMetro();
}
、、省略其他方式
return Strategy;
}
代码的实现逻辑下沉到子类中去完成,代码清爽,逻辑清晰。但是如果实现的子类有几十个怎么办呢?就像中国有34个 省份难道要写34个if(这个是我实际工作中遇见的场景)进一步优化,我们可以把初始化的动作放在Map里当然也可以利用数组,在类加载的时候就把需要 的对象初始化好
public TravelStrategy travel (String type){
TravelStrategy strategy = map.get(type);
}
最后代码是这个样子的,其实这是内存用空间换来的,牺牲掉了一部分内存空间换来了干掉了几十个if, 那么有没有其他的写法呢?其实我们还可以用枚举,枚举也是可以有构造函数
public enum TravelEnum {
TRAIN("TRAIN",new StrategyTrain()),
BUS("BUS",new StrategyBus());
private TravelStrategy strategy;
// 构造方法里传入对象实例
PayEnum(String name,TravelStrategy strategy) {
this.name = name;
this.strategy = strategy;
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(TravelStrategy strategy) {
this.strategy = strategy;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 根据名称获取策略(这里避免了写过多的if-else-if/case-when)
* @param name
* @return
*/
public static TravelStrategy getStrategy(String name) {
for(TravelEnum travel : TravelEnum.values()) {
if (travel.name.equals(name)) {
return travel.strategy;
}
}
return null;
}
}
总结:
/**
* if-else-if 优化办法
*
* 1、多态+map
* 2、多态+枚举
* 3、多态+数组
* 4、使用卫语句,将复杂的条件表达式拆分成多个条件表达式
* 5、反射
* 6、Spring注入一个集合
* @Autowired
* List<Strategy> strategyList Strategy子类有一个标识字段 */
关于策略模式可以参考:juejin.cn/post/694431…
你有什么好的实现方式或者建议欢迎留言