【Java】项目代码 if/else 过多,引起程序猿口吐莲花

项目代码 if/else 过多,引起程序猿口吐莲花

大道七哥发布于 37 分钟前

一、吐槽模式

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

//就像这样,一步一步变成金字塔

if (condition1) {

action1();

if (condition2) {

action2();

if (condition3) {

action3();

if (condition4) {

action4();

}

}

}

}

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

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

其他

那么过多的 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);

}

}

三、各抒己见

其他

java设计模式

阅读 21发布于 37 分钟前

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

大道七哥

一个用灵魂写代码的段子手

11 声望

0 粉丝

0 条评论

得票时间

avatar

大道七哥

一个用灵魂写代码的段子手

11 声望

0 粉丝

宣传栏

一、吐槽模式

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

//就像这样,一步一步变成金字塔

if (condition1) {

action1();

if (condition2) {

action2();

if (condition3) {

action3();

if (condition4) {

action4();

}

}

}

}

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

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

其他

那么过多的 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);

}

}

三、各抒己见

其他

以上是 【Java】项目代码 if/else 过多,引起程序猿口吐莲花 的全部内容, 来源链接: www.h5w3.com/114166.html

回到顶部