乐趣区

关于java:项目代码-ifelse-过多引起程序猿口吐莲花

一、吐槽模式

我的项目开发周期短,迭代速度快,工夫久了之后,代码中可能会充斥着大量的 if/else,一层一层的嵌套,让人短时间内不可能领悟该段代码的逻辑,长此以往,前面接手的人可能真的会口吐莲花!

// 就像这样,一步一步变成金字塔
if (condition1) {action1();
    if (condition2) {action2();
        if (condition3) {action3();
            if (condition4) {action4();
            }
        }
    }
}

每当咱们接手这样的一个老我的项目,可能会默默的开启吐槽模式

1. 这我的项目怎么感觉毫无设计,想啥做啥,太坑了吧
2. 这尼玛全是逻辑判断,也没正文,看 NM 啊
3. 逻辑嵌套这么多,看死我了,谁写的垃圾代码?
4. 我先忍忍吧,不行,我也跑路了 …

程序猿何苦尴尬程序猿呢,谁不想做个好猿,你看老板给你机会吗,“三天工夫,不能再多了,周一上线”

那么过多的 if…else,咱们该如何去优化呢,让咱们的程序看起来更加清新一点?也为我的项目的后续接手人,加重点累赘,少吐槽一点。

二、解决形式

提前返回

说白了就是判断条件取反,让程序不满足条件是提前返回,代码在逻辑表白上会更清晰,看上面代码:

if (condition) {// do something} else {return xxx;}

// 换成先判断!condition,去掉 else
if (!condition) {return xxx;} 
// do something

Optional

Optional 次要用于非空判断,是 jdk8 中新的个性,所以应用的不是特地多。

// 如果登录用户为空,执行 action1,否则执行 action 2
// 用之前
if (user == null) {//do action 1} else {//do action2}
// 用之后
Optional<User> userOptional = Optional.ofNullable(user);
userOptional.map(action1).orElse(action2);

// 应用 Optional 优化之后,让非空校验更加优雅,间接的缩小 if 操作

Assert

Assert 能够帮忙咱们实现各种参数验证,比方字符串不为空等。还有其余很多框架类库,例如 Spring、Apache Commons 都提供了工具类,用于实现这种通用的性能,这样大家就不用自行编写 if…else 了。
例如:

Assert.hasText(param.getType(), "参数类型不能为空");

对于 Spring 的 Assert 类,能够查阅:https://docs.spring.io/spring…

表驱动法

逻辑表白模式固定的 if/else 代码,能够通过映射关系,将逻辑表达式用表格的形式示意,再应用表格查找的形式,找到某个输出所对应的处理函数,应用这个处理函数进行运算。
例如:

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

采纳表驱动法重构后

Map<?, Function<?> action> actionMappings = new HashMap<>();

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

// 省略 null 判断
actionMappings.get(param).apply(someParams);

表的映射关系,能够采纳集中的形式,也能够采纳扩散的形式,即每个解决类自行注册,也能够通过配置文件的形式。

事件驱动

通过关联不同的事件类型和对应的解决机制,来实现简单的逻辑,同时达到解耦的目标。从实践角度讲,事件驱动能够看做是表驱动的一种,但从实际角度讲,事件驱动和后面提到的表驱动有多处不同。次要体现为:

表驱动通常是一对一的关系;事件驱动通常是一对多;

表驱动中,触发和执行通常是强依赖;事件驱动中,触发和执行是弱依赖

正是上述两者不同,导致两者实用场景的不同,具体来说,事件驱动可用于如订单领取实现触发库存、物流、积分等性能。

注解驱动

通过 Java 注解(或其它语言的相似机制)定义执行某个办法的条件。在程序执行时,通过比照入参加注解中定义的条件是否匹配,再决定是否调用此办法。注解驱动,很多框架中都能看到这种模式的应用,比方咱们常常用的 Spring 中,具体实例,大家能够参考:https://www.cnblogs.com/houzh…

策略模式

针对以下四种策略的场景,咱们采纳两种优化计划来举例

if (strategy.equals("fast")) {//do FAST action} else if (strategy.equals("normal")) {//do NORMAL action} else if (strategy.equals("smooth")) {//do SMOOTH action} else if (strategy.equals("slow")) {//do SLOW action}

多态

interface Strategy {void run() throws Exception;
}

class FastStrategy implements Strategy {
    @Override
    void run() throws Exception {//do FAST action}
}

class NormalStrategy implements Strategy {
    @Override
    void run() throws Exception {//do NORMAL action}
}

class SmoothStrategy implements Strategy {
    @Override
    void run() throws Exception {//do SMOOTH action}
}

class SlowStrategy implements Strategy {
    @Override
    void run() throws Exception {//do SLOW action}
}

// 调用伪代码(此处能够 map 对象来保留策略,或者反射调用,或者交给 spring 获取 bean 等形式很多)Strategy strategy = map.get(param);
strategy.run();

枚举

在枚举中定义方法,合成逻辑调用

public enum Strategy {
    FAST {
        @Override
        void run() {//do FAST action}
    },
    NORMAL {
        @Override
        void run() {//do NORMAL action}
    },

    SMOOTH {
        @Override
        void run() {//do SMOOTH action}
    },

    SLOW {
        @Override
        void run() {//do SLOW action}
    };

    abstract void run();}

// 调用伪代码
Strategy strategy = Strategy.valueOf(param);
strategy.run();

职责链模式

当 if…else 中的条件表达式灵便多变,无奈将条件中的数据抽象为表格并用对立的形式进行判断时,这时应将对条件的判断权交给每个性能组件。并用链的模式将这些组件串联起来,造成残缺的性能,实用于条件表达式灵便多变,没有对立模式的场景。

实现与示例

// 重构前
public void handle(request) {if (handlerA.canHandle(request)) {handlerA.handleRequest(request);
    } else if (handlerB.canHandle(request)) {handlerB.handleRequest(request);
    } else if (handlerC.canHandle(request)) {handlerC.handleRequest(request);
    }
}
// 重构后
public void handle(request) {handlerA.handleRequest(request);
}

public abstract class Handler {
  protected Handler next;
  public abstract void handleRequest(Request request);
  public void setNext(Handler next) {this.next = next;}
}

public class HandlerA extends Handler {public void handleRequest(Request request) {if (canHandle(request)) doHandle(request);
    else if (next != null) next.handleRequest(request);
  }
}

三、畅所欲言

道友 A:策略带来更多的代码量,逻辑也不是高深莫测,还不如 if/else,老夫就喜爱 if/else,哈哈哈
道友 B:我不多写点 if/else,不让代码看起来绕绕的,怎么体现我的工作量
道友 C:我都写了这么多代码了,你才通知我能够这么优化,我太累了
道友 D:为啥不必 switch,switch 比 if/else 看起来难受多了
道友 E:工作太忙,加班太多,回绝了发言 …

退出移动版