优化代码中的if-else

小白也可以写出很优雅的代码

前言

在日常的开发中,可能会由于迭代时间紧等原因,不会过多的去考虑代码质量,遇到逻辑,直接if-else。本文主要来谈谈优化代码中的if-else的一些方法。

提前return

优化前:

if(condition){
    //doSomething
}else{
    return ;
}

 

刚开始实习的时候,就一直用上面的这种写法,还会给每个条件加上注释。一旦doSomething中的代码变多,整个代码可读性就会变差,也不优雅。后来在师父的指导下,改成了下面这种。

优化后:

if(!condition){
    return ;
}
//doSomething

使用三目运算符

优化前:

int  price ;
if(condition){
    price = 80;
}else{
    price = 100;
}

 

优化后:

int price = condition?80:100;

使用枚举

优化前:

String OrderStatusDes;
if(orderStatus==0){
    OrderStatusDes ="订单未支付";
}else if(OrderStatus==1){
    OrderStatusDes ="订单已支付";
}else if(OrderStatus==2){
   OrderStatusDes ="已发货"; 
}

 

优化后:

// 先定义一个枚举
@Getter
public enum OrderStatusEnum {
    UN_PAID(0,"订单未支付"),PAIDED(1,"订单已支付"),SENDED(2,"已发货");
    
    private int code;
    private String desc;

    OrderStatusEnum(int code, String desc){
        this.code = code;
        this.desc = desc;
    }

    OrderStatusEnum getByCode(int orderStatus) {
        for (OrderStatusEnum temp : OrderStatusEnum.values()) {
            if (temp.getCode() == orderStatus) {
                return temp;
            }
        }
        return null;
    }
}
// 然后上面的一堆if else就可以优化成一行代码
String OrderStatusDes = OrderStatusEnum.getByCode(orderStatus).getDesc();

 

上面这个逻辑比较简单,如果逻辑比较多,还可以在枚举类中定义方法,不过目前在我所接触的项目中还没有遇到。例如:

// 定义一个枚举类
public enum Status {
    NEW(0) {
      @Override
      void run() {
        //do something
      }
    },
    RUNNABLE(1) {
      @Override
       void run() {
         //do something
      }
    };
    public int statusCode;
    abstract void run();
    Status(int statusCode){
        this.statusCode = statusCode;
    }
}
Status status = Status .valueOf(param);
status.run();

 

使用 Optional

Optional是Java8的新特性。有时候if-else比较多,是因为非空判断导致的,这个时候就可以派上用场了。

优化前

String str = "jay@huaxiao";
if (str != null) {
    System.out.println(str);
} else {
    System.out.println("Null");
}

 

优化后:

Optional<String> strOptional = Optional.of("jay@huaxiao");
strOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));

 

关于Optional的一些API和进一步学习,推荐阅读这篇文章:还在重复写空指针检查代码?考虑使用 Optional 吧!

表驱动法

这是一种编程模式,是一种使你可以在表中查找信息,而不必用很多的逻辑语句(if或Case)来把它们找出来的方法。举个例子。

优化前:

if (param.equals(value1)) {
    doAction1(someParams);
} else if (param.equals(value2)) {
    doAction2(someParams);
} else if (param.equals(value3)) {
    doAction3(someParams);
}
// ...

 

下面的优化,会把map抽象成表,在map中查找信息,而省去不必要的逻辑语句。

优化后:

Map<?, Function<?> action> actionMappings = new HashMap<>(); // 这里泛型 ? 是为方便演示,实际可替换为你需要的类型

// 初始化
@PostConstruct
public void init(){
    actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
    actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
    actionMappings.put(value3, (someParams) -> { doAction3(someParams)});
}

// 省略多余逻辑语句
actionMappings.get(param).apply(someParams);

 

而其中的doAction,还可以进一步抽象出一个service服务,专门放其中的逻辑。

策略模式+工厂方法

优化前:

String medalType = "guest";
if ("guest".equals(medalType)) {
    System.out.println("展示嘉宾勋章");
 } else if ("vip".equals(medalType)) {
    System.out.println("展示会员勋章");
} else if ("guard".equals(medalType)) {
    System.out.println("展示守护勋章");
}

 

优化后:

首先,进行抽象,把每个逻辑代码块,抽象成一个公共的接口。示例中是展示勋章,可以写出如下的代码:

//勋章接口
public interface IMedalService {
    void showMedal();
}

 

然后,根据不同的条件,定义对应的策略实现类:

//守护勋章策略实现类
public class GuardMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
        System.out.println("展示守护勋章");
    }
}
//嘉宾勋章策略实现类
public class GuestMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
        System.out.println("展示嘉宾勋章");
    }
}
//VIP勋章策略实现类
public class VipMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
        System.out.println("展示会员勋章");
    }
}

 

最后,再定义工厂类,用于管理实现的这些策略类:

//勋章服务工产类
public class MedalServicesFactory {

    private static final Map<String, IMedalService> map = new HashMap<>();
    static {
        map.put("guard", new GuardMedalServiceImpl());
        map.put("vip", new VipMedalServiceImpl());
        map.put("guest", new GuestMedalServiceImpl());
    }
    public static IMedalService getMedalService(String medalType) {
        return map.get(medalType);
    }
}

 

使用:

String medalType = "guest"; 
IMedalService medalService = MedalServicesFactory.getMedalService(medalType); 
medalService.showMedal();

 

上面这种优化方案有一个弊端,当添加一个新策略的时候,还需要手动添加到工厂类的map中,容易被忽略。

总结

对if-else进行适当的优化,能够是代码变得优雅,同时还可以降低耦合性,利于后期的扩展等。但也有缺点,增加了代码的阅读门槛,不够直观,特别是业务非常复杂的情况下,没法清晰的展示各个类、接口之间的关系。我很想知道在我们公司的项目中,有没有实操的逻辑,但就我目前参与的项目,实在是没有看到,可能还是因为业务不够复杂吧。不过,项目中已经出现了类似屎山的情况,一个列表接口,有很多种查询条件,代码中用了非常多的if-else,同时一些逻辑也侵入到了XML中的SQL,如果后续会进行优化的话,我再补充。

参考

if-else代码优化的八种方案

面试官:优化代码中大量的if/else,你有什么方案?

人已赞赏
数据结构编程语言

数据结构之二叉树(一)

2020-6-17 20:16:54

Mysql编程语言

浅谈MYSQL与JSON相关的操作

2020-8-2 15:10:56

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索