⾼薪程序员⾯试题精讲系列17之Java代码中如果有太多if语句
该如何优化?
⼀. 今⽇题⽬
我们在⾯试时,⾯试官会从各个⽅⾯考察我们到底有没有参与过项⽬,既会考察我们对某个技能的掌握和理解情况,也会考察我们的编程习惯和技巧。⽐如,有这么⼀道⾯试题:
如果你的项⽬代码中,有⼤量的if/else语句,你有什么优化解决⽅案?
⼆. 题⽬剖析
我们在平时开发写的代码中,if-else判断语句基本是必不可少的。当我们只有⼀两层判断语句嵌套的时候其实还好,但是当我们过度地、不必要地使⽤ if...else语句,就会对代码的可读性、可扩展性造成负⾯影响。另外如果判断语句越来越多,后期进⾏项⽬维护也会⽐较困难,对于后⾯接⼿项⽬的⼈来说,也是⼀个很头疼的问题。
所以去除代码中过多的if...else语句,就是对程序员软件重构、设计模式、⾯向对象设计、架构模式、数据结构等多⽅⾯技术综合运⽤能⼒的反映了。所以我们的代码中要合理使⽤ if...else,既不能没有,也不能过度。这些对某个技术的综合、合理地运⽤,都需要程我们序员在⼯作中不断的摸索总结。
这也是这道⾯试题的考察⽬的!
三. 存在问题
1. ⽰例代码
壹哥 先给各位展⽰如下⼀段代码,请回忆⼀下,在你之前的项⽬中,有没有如下风格的代码,在⼀个类或⽅法中,有⼤量的if...lse..的代码。
1if (condition1) {
2    doSomeThing1();
3} else if (condition2) {
4    doSomeThing2();
5} else if (condition3) {
6    doSomeThing3();
7} else if (condition4) {
8    doSomeThing4();
9} else {
10    doSomeThing5();
11}...
这样的代码,就是if与else的堆叠,功能当然可以实现,就是代码看起来总归是怪怪的。据说某⼤⼚中,某些复杂的业务就是这样if...嵌套来嵌套去的。对于后⾯项⽬维护改造来说,这样的代码看起来真的是⼀个让⼈头疼恶⼼的“屎⼭屑海”。
2. 问题原因
那么为什么会出现上⾯这样的代码呢?其实出现这种情况的原因有很多,⽐如
其实基本上就是前期迭代懒得优化,来⼀个需求,就加⼀个if,再来⼀个需求,就再加⼀个if。久⽽久之,就成了if...else叠罗汉了。
四. 解决⽅案
那么我们该如何解决代码中过多的if...else语句呢?可以考虑采⽤以下解决⽅案。
1. 适时的return;
2. ⽤switch或三⽬运算符替换;
3. 策略模式:多态、函数式编程、枚举;
4. 使⽤Optional;
5. 使⽤Assert;
6. 表驱动模式;
7. 职责链模式;
8. 注解驱动;
9. 事件驱动;
10. 有限状态机
1. 适时的return
⽐如我们有以下的代码:
1if (condition) {
2 // do something
3} else {
4 return xxx;
5}
其实上⾯的代码完全可以按如下⽅式优化:
1if (!condition) {
2 return xxx;
3}
4
5// do something
我们先判断!condition,将return语句放在前⾯,这样就可以去掉else语句了,相对于上⾯的语句代码清晰了不少。
2. ⽤switch或三⽬运算符替换
对符合特定条件的if语句,可以考虑选择switch或三⽬运算符进⾏替换,这⾥不做详细展⽰描述。
3. 策略模式
3.1 策略模式概念
策略模式作为⼀种软件设计模式,指对象有某个⾏为,但在不同的场景中,该⾏为有不同的实现算法。在策略模式(Strategy Pattern)中,⼀个类的⾏为或其算法可以在运⾏时更改,这种类型的设计模
式属于⾏为型模式。策略模式由以下3种⾓⾊组成:
1. 抽象策略⾓⾊(Strategy):策略类,通常由⼀个接⼝或者抽象类实现。
2. 具体策略⾓⾊(ConcreteStrategy):包装了相关的算法和⾏为。
3. 环境⾓⾊(Context):持有⼀个策略类的引⽤,最终给客户端调⽤。
3.2 策略模式使⽤场景
1. 针对同⼀类型的问题有多种处理⽅式,仅仅是具体的处理⽅法有差别时。
2. 出现同⼀抽象类有多个⼦类,⽽⼜需要使⽤ if-else 或者 switch-case 来选择具体⼦类时。
3.3 策略模式具体案例
⽐如有这么⼀个开发场景,我们要根据不同的性别执⾏不同的操作,类似的这种场景是很常见的。通常的实现如下:
1if ("man".equals(strategy)) {
2 // 执⾏男⼈相关操作
3} else if ("woman".equals(strategy)) {
4 // 执⾏⼥⼈相关操作
5} else if ("other".equals(strategy)) {
6 // 执⾏其他操作
7}
对于以上的代码,我们可以采⽤以下策略进⾏优化。
3.3.1 以多态的策略优化模式
⾸先定义⼀个接⼝类Strategy。
1public interface Strategy {
2
3    void run() throws Exception;
4
5}
然后写若⼲个实现类:
1//男⼈的策略实现类
2@Slf4j
3public class ManStrategy implements Strategy {
4
5    @Override
6    public void run() throws Exception {
7        // 快速男⼈的逻辑
8        log.debug("执⾏男⼈相关的逻辑...");
9    }
10
11}
12
13//⼥⼈的策略实现类
14@Slf4j
15public class WomanStrategy implements Strategy {
16
17    @Override
18    public void run() throws Exception {
19        // 快速⼥⼈的逻辑
20        log.debug("执⾏⼥⼈相关的逻辑...");
21    }
22
23}
24
25//其他⼈的策略实现类
26@Slf4j
27public class OtherStrategy implements Strategy {
28
29    @Override
30    public void run() throws Exception {
31        // 快速其他的逻辑
32        log.debug("执⾏其他相关的逻辑...");
33    }
34
35}
具体使⽤简单⽰例:
1public class StrategyTest {
2
3    public static void main(String[] args) {
4        try {
5            Strategy strategy = initMap("man");
6            strategy.run();
7        } catch (Exception e) {
8              e.printStackTrace();
9        }
10    }
11
12    //初始化Map,获取某个性别策略
13    private static Strategy initMap(String key) {
14        //使⽤简单⽰例
15        HashMap<String, Strategy> map = new HashMap<>();
16        map.put("man", new ManStrategy());
17        map.put("woman", new WomanStrategy());
18        map.put("other", new OtherStrategy());
19        (key);
20    }
21
22}
该⽅案的缺点:
这种优化⽅案有⼀个弊端:为了能够快速拿到对应的实现策略,需要⼀个map对象来保存实现策略,当添加⼀个新策略的时候,还需要⼿动添加到这个map中,容易被忽略。
3.3.2 以函数式编程的策略优化模式
我们可以对上⾯的代码进⾏稍作修改,采⽤Java8⾥的函数式编程⽅法来简化代码。
⾸先定义⼀个interface接⼝。
1public interface Strategy {
2
3    void run() throws Exception;
4}
然后使⽤函数式编程进⾏代码的操作。
1@Slf4j
2public class StrategyTest {
3
4    public static void main(String[] args) {
怎样写代码 自己做编程5        //使⽤简单⽰例
6        HashMap<String, Strategy> map = new HashMap<>();
7        map.put("man", () -> log.debug("执⾏男⼈相关的逻辑..."));
8        map.put("woman", () -> log.debug("执⾏⼥⼈相关的逻辑..."));
9        map.put("other", () -> log.debug("执⾏其他⼈相关的逻辑..."));
10
11        try {
12            ("woman").run();
13        } catch (Exception e) {
14              e.printStackTrace();
15        }
16    }
17
18}
3.3.3 以枚举的策略优化模式
定义⼀个枚举策略类。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。