面试题:代码中有大量的if-else应该如何优化

4 篇文章 0 订阅
1 篇文章 0 订阅
本文介绍了如何通过多态、设计模式(如策略模式和责任链模式)以及函数式编程来优化代码中的大量if-else语句,提升代码的可读性和可维护性。作者给出了具体实例,包括角色权限管理、计算器运算和命令处理等场景的优化方法。
摘要由CSDN通过智能技术生成


前言

面试官问:代码中有大量的if-else应该如何优化?
接下来,我带你一步一步征服面试官!

觉得不错的同学可以加我公众号,会经常分享一些技术干货,以及热点AI和科技新闻
在这里插入图片描述


一、思路

首先我们要想,大量的if-else怎么会减少呢?其实就是要将一坨奥利给分散,变成一块块巧克力,那无非就是分散到不同类、不同方法、或者lambda表达式

我提供几种思路:

  • 多态,将条件分支的处理逻辑封装在不同的子类中,并通过父类的引用来调用具体的子类对象。这样可以将 if-else 的条件判断转移到运行时的对象绑定过程中。
  • 设计模式,策略模式、工厂模式、状态模式,这些设计模式可以将不同的条件分支逻辑封装到独立的类中,提高代码的可读性和可维护性。
  • 使用函数式编程,使用函数式编程的特性如高阶函数、Lambda 表达式等来处理条件分支。函数式编程可以将条件判断转化为函数调用,简化代码逻辑,并提高代码的可读性。
  • 重构代码,通过代码重构技术,将复杂的条件逻辑拆分成多个简单的方法或类,每个方法或类只处理特定的条件分支。这样可以提高代码的可读性和可维护性。

其实不管是那种思路,最后你都还是免不了要去匹配到某个类、某个方法、某个函数调用

二、实现

2.1 多态

假设您有一个系统,根据用户的角色来执行不同的操作。原始的 if-else 逻辑可能如下所示:

public class UserService {
    public void performOperation(User user) {
        if (user.getRole() == UserRole.ADMIN) {
            // 管理员权限逻辑
        } else if (user.getRole() == UserRole.USER) {
            // 用户权限逻辑
        } else if (user.getRole() == UserRole.GUEST) {
            // 游客权限逻辑
        }
    }
}

现在,我们可以通过多态来优化这段代码。首先,定义一个抽象的角色类 UserRole,然后为每种角色创建具体的子类,并在每个子类中重写 performOperation 方法。

public abstract class UserRole {
    public abstract void performOperation();
}

public class AdminRole extends UserRole {
    @Override
    public void performOperation() {
        // 管理员权限逻辑
    }
}

public class UserRole extends UserRole {
    @Override
    public void performOperation() {
        // 用户权限逻辑
    }
}

public class GuestRole extends UserRole {
    @Override
    public void performOperation() {
        // 游客权限逻辑
    }
}

现在,您的 UserService 可以根据不同的用户角色调用相应的 performOperation 方法,而不再需要复杂的 if-else 逻辑。

public class UserService {
    public void performOperation(UserRole role) {
        role.performOperation();
    }
}

在调用处,您可以根据不同的用户角色创建相应的子类对象,然后传递给 UserService 来执行相应的操作。

public class Main {
    public static void main(String[] args) {
        UserRole userRole = new AdminRole(); // 或者其他角色
        UserService userService = new UserService();
        userService.performOperation(userRole);
    }
}

2.2 设计模式

这里拿策略模式来举例说明:

假设您有一个计算器程序,根据用户选择的运算符执行不同的计算操作。原始的 if-else 逻辑可能如下所示:

public class Calculator {
    public int calculate(int a, int b, String operator) {
        if (operator.equals("+")) {
            return a + b;
        } else if (operator.equals("-")) {
            return a - b;
        } else if (operator.equals("*")) {
            return a * b;
        } else if (operator.equals("/")) {
            return a / b;
        }
        throw new IllegalArgumentException("Invalid operator: " + operator);
    }
}

现在,我们可以使用策略模式来重构代码。首先,定义一个接口 Operation,然后为每种运算符创建具体的实现类,并在每个实现类中重写 calculate 方法。

public interface Operation {
    int calculate(int a, int b);
}

public class Addition implements Operation {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
}

public class Subtraction implements Operation {
    @Override
    public int calculate(int a, int b) {
        return a - b;
    }
}

// 同样地,乘法和除法的实现类也可以类似地定义

然后,在 Calculator 类中引入 Operation 接口,并根据不同的运算符选择相应的实现类来执行计算。

public class Calculator {
    private Operation operation;

    public void setOperation(Operation operation) {
        this.operation = operation;
    }

    public int calculate(int a, int b) {
        return operation.calculate(a, b);
    }
}

在调用处,您可以根据用户选择的运算符创建相应的实现类对象,并将其传递给 Calculator 来执行相应的计算操作。

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        calculator.setOperation(new Addition()); // 或者其他运算符的实现类
        int result = calculator.calculate(10, 5);
        System.out.println("Result: " + result);
    }
}

通过使用策略模式,您可以将各种运算符的计算逻辑封装在单独的类中,并根据需要动态地选择不同的实现类来执行计算,从而避免了大量的 if-else 语句。

补充

还有一种特殊的 场景 可以使用责任链模式来优化,看下面的例子:

public void check(Integer status) {
	if (status == 1) {
		// balaba
		status++;
		check(status);
	} 
	if (status == 2) {
		// bababa
		status++;
		check(status);
	}
	if (status == 3) {
		// lalal
		status++;
		check(status);
	} else if ...
}

这种有固定执行顺序的就可以使用责任链模式

2.3 函数式编程

假设您有一个程序,根据用户输入的不同命令执行不同的操作。原始的 if-else 逻辑可能如下所示:

public class CommandHandler {
    public void handle(String command) {
        if ("start".equals(command)) {
            start();
        } else if ("stop".equals(command)) {
            stop();
        } else if ("restart".equals(command)) {
            restart();
        } else {
            unknownCommand();
        }
    }

    private void start() {
        System.out.println("Starting...");
    }

    private void stop() {
        System.out.println("Stopping...");
    }

    private void restart() {
        System.out.println("Restarting...");
    }

    private void unknownCommand() {
        System.out.println("Unknown command");
    }
}

现在,我们可以使用函数式编程风格重构代码。首先,定义一个接口 Command,并在其中声明一个方法来执行命令,然后,我们可以为每个命令创建一个具体的实现类,并在其中实现相应的操作:

@FunctionalInterface
public interface Command {
    void execute();
}

public class StartCommand implements Command {
    @Override
    public void execute() {
        System.out.println("Starting...");
    }
}

public class StopCommand implements Command {
    @Override
    public void execute() {
        System.out.println("Stopping...");
    }
}

public class RestartCommand implements Command {
    @Override
    public void execute() {
        System.out.println("Restarting...");
    }
}


在 CommandHandler 类中,我们可以使用一个 Map 来将命令名称映射到相应的命令对象,并根据用户输入执行相应的命令,在调用处,您只需创建一个 CommandHandler 对象,并调用其 handle 方法传入用户输入的命令即可:

import java.util.HashMap;
import java.util.Map;

public class CommandHandler {
    private final Map<String, Command> commandMap = new HashMap<>();

    public CommandHandler() {
        commandMap.put("start", new StartCommand());
        commandMap.put("stop", new StopCommand());
        commandMap.put("restart", new RestartCommand());
    }

    public void handle(String command) {
        Command cmd = commandMap.getOrDefault(command, () -> System.out.println("Unknown command"));
        cmd.execute();
    }
}

public class Main {
    public static void main(String[] args) {
        CommandHandler handler = new CommandHandler();
        handler.handle("start"); // 或者其他命令
    }
}


通过使用函数式编程风格,我们将各种命令的执行逻辑封装在单独的类中,并通过 lambda 表达式和函数式接口将命令与其操作关联起来,从而避免了大量的 if-else 语句。

三、优化

那么既然将代码拆分了,想要去匹配到正确的逻辑,要分情况考虑

3.1 简单条件

if (status == 1) {
	// balaba
} else if (status == 2) {
	// bababa
} else if (status == 3) {
	// lalal
} else if ....
if (status == 1 && type == 'a') {
	// balaba
} else if (status == 2 && type == 'b') {
	// bababa
} else if (status == 3 && type == 'c') {
	// lalal
} else if ....

可以看到,这种条件都是固定的参数和判断格式,此时我们可以使用map、数组等来优化,可以参考上面的函数式编程,将不同的实现或者函数提前放到一个map中,需要的时候直接get即可。

3.2 复杂条件

if (number > 1) {
	if (number > 2) {
		// bababa
	} else if (number < 10) {
		// lalal
	}
} else if (number == 1) {
	// bababa
} else {
	if (number < -5) {
	// lalal
	} else if ....
}
if (status == 1 && type == 'a') {
	// balaba
} else if (status == 2 || type == 'b') {
	// bababa
} else if (status == 3 || type == 'c') {
	// lalal
} else if ....

这种无法使用map和数组来实现,但是可以改变使用List,将不同的实现放到一个List中,然后使用for循环遍历接口实现类,接口定义一个方法专门来校验,返回boolean,如果是true就执行对应的方法。


总结

上述总结了常见场景下的一些优化思路,但是实际场景可能更加复杂,需要根据具体情况具体分析,有时候,可能不变更加合适。

希望大家工作顺利,成长飞速~~~

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

romanYSX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值