条件语句的多层嵌套问题优化,助你写出不让同事吐槽的代码

简介: 前言《阿里巴巴开发手册》中,有关于多 if-else 分支和嵌套的建议和解决方案,如下:那么本文介绍几种优化方案,给大家提供一些思路案例下面是开发中可能会遇到的典型代码:这种情况,我们如何替代多分支和分支嵌套问题呢?如何让代码变得更容易维护和拓展呢?可以先自己思考一下哈..........下面我提供几种方法吧卫语句《重构--改善既有代码的设计》 书籍中有有如下描述:如果某个条件极其罕见,就应该单独检查该条件,并在条件为真时立即从函数中返回。这样的单独检查常常被称为 “卫语句”。使用卫语句,我们可以对上面的示例修改为:先进行条件检查,然后将 if-else 逻辑转成对应的卫语句格式。枚举《Eff

前言

《阿里巴巴开发手册》中,有关于多 if-else 分支和嵌套的建议和解决方案,如下:

那么本文介绍几种优化方案,给大家提供一些思路


案例

下面是开发中可能会遇到的典型代码:

public String getTweetTitle(int type) {
        String result;
        if (type == 0) {
            throw new IllegalArgumentException("参数有误");
        }
        //长贴-->获得长帖标题
        if (isPaperTweet(type)) {
            result = getPaperTweetTitle();
        } else {
            // 视频贴-->获得视频贴标题
            if (isVideoTweet(type)) {
                result = getVideoTitle();
            } else {
                result = getDefaultTitle();
            }
        }
        return result;
    }

这种情况,我们如何替代多分支和分支嵌套问题呢?如何让代码变得更容易维护和拓展呢?

可以先自己思考一下哈..........

下面我提供几种方法吧


卫语句

《重构--改善既有代码的设计》 书籍中有有如下描述:

如果某个条件极其罕见,就应该单独检查该条件,并在条件为真时立即从函数中返回。这样的单独检查常常被称为 “卫语句”。

使用卫语句,我们可以对上面的示例修改为:

public String getTweetTitle(int type) {
        // 条件检查
        if (type == 0) {
            throw new IllegalArgumentException("参数有误");
        }
        // 长贴-->获得长帖标题
        if (isPaperTweet(type)) {
            return getPaperTweetTitle();
        }
        // 视频贴-->获得视频贴标题
        if (isVideoTweet(type)) {
            return getVideoTitle();
        }
        return getDefaultTitle();
    }

先进行条件检查,然后将 if-else 逻辑转成对应的卫语句格式。


枚举

《Effective Java 中文版》 中第 30 条 :用 enum 代替 int 常量 小节有描述:使用枚举,来替代分支语句,虽然失去了简洁性,但是更加安全和灵活。

通过在枚举内部定义抽象函数,每个枚举常量重写该函数,这样根据枚举值获取枚举常量后调用该函数即可获得期待的计算结果。

示例代码如下:

public enum TweetStrategyEnum {
    PAPER(1) {
        @Override
        double getTitle() {
            return "长贴标题";
        }
    },
    VIDEO_TWEET(2) {
        @Override
        double getTitle() {
            return "视频贴标题";
        }
    },
    DEFAULT_TWEET(3) {
        @Override
        double getTitle() {
            return "短贴标题";
        }
    };
    private final int type;
    TweetStrategyEnum(int type) {
        this.type = type;
    }
    abstract String getTitle();
    public static TweetStrategyEnum valueOf(int type) {
        for (TweetStrategyEnum tweetStrategyEnum : TweetStrategyEnum.values()) {
            if (tweetStrategyEnum.type == type) {
                return tweetStrategyEnum;
            }
        }
        return null;
    }
}

使用时根据枚举值获取枚举对象,直接调用该枚举常量对应的策略:

public void getTitle() {
        TweetStrategyEnum tweetStrategyEnum = TweetStrategyEnum.valueOf(1);
        if(tweetStrategyEnum != null){
            System.out.println(tweetStrategyEnum.getTitle());
        }
    }


状态模式

《设计模式之禅》 状态模式章节中讲到:

状态模式的其中一个优点就是 “结构清晰”。状态模式体现了开闭原则和单一职责原则,易于拓展和维护。

所谓的结构清晰就是避免了过多的 switch-case 或者 if-else 语句的使用,避免了程序的复杂性,提高了程序的可维护性。

《设计模式之禅》书提供的案例和文章上面给出的非常类似,根据当前状态来执行不同的行为,有兴趣可以翻出看看

同样优化下上面的案例代码:

定义一个状态行为接口

public interface TweetState {
    String getTitle();
}

定义多个具体的状态实现

public class VideoTweetState implements TweetState{
    @Override
    public String getTitle() {
        return "视频贴";
    }
}
public class PaperTweetState implements TweetState{
    @Override
    public String getTitle() {
        return "长贴标题";
    }
}
public class DefaultTweetState implements TweetState{
    @Override
    public String getTitle() {
        return "短贴标题";
    }
}

定义一个状态使用的client

public class Client {
    private TweetState tweetState;
    public TweetState getTweetState() {
        return tweetState;
    }
    public void setTweetState(TweetState tweetState) {
        this.tweetState = tweetState;
    }
    public void getTitle() {
        tweetState.getTitle();
    }
}

外部使用

public static void main(String[] args) {
        Client client = new Client();
        client.setTweetState(new VideoTweetState());
        client.getTitle();
    }


策略+工厂模式

首先,我们把每个条件逻辑代码块,抽象成一个公共的接口,可以得出以下代码:

public interface ITweetService {
    String getTitle();
}

我们根据每个逻辑条件,定义相对应的策略实现类,可得以下代码:

public class PaperTweetServiceImpl implements ITweetService{
    @Override
    public String getTitle() {
        return "长贴标题";
    }
}
public class VideoTweetServiceImpl implements ITweetService{
    @Override
    public String getTitle() {
        return "视频贴标题";
    }
}

接下来,我们再定义策略工厂类,用来管理这些策略类,如下:

public class TweetServicesFactory {
    private static final Map<String, ITweetService> map = new HashMap<>();
    static {
        map.put("paperTweet", new PaperTweetServiceImpl());
        map.put("videoTweet", new VideoTweetServiceImpl());
    }
    public static ITweetService getTweetService(String type) {
        return map.get(type);
    }
}
public static void main(String[] args) {
        ITweetService tweetService = TweetServicesFactory.getITweetService(1);
        tweetService.getTitle();
    }


总结

本文主要讲了如何解决 if-else 语句拓展性和多层嵌套问题。可以通过卫语句、枚举、状态模式、策略+工厂模式等方式解决,如果大家有更好的方案,可以和我交流

希望大家能够在实际开发中尝试使用这些方法来编写更加优雅的代码。

最后

觉得不错,记得点赞,转发,分享,谢谢


相关文章
|
C# 索引 Windows
Winform控件优化之TabControl控件的使用和常用功能
TabControl是一个分页切换(tab)控件,不同的页框内可以呈现不同的内容,将主要介绍调整tab的左右侧显示、设置多行tab、禁用或删除tabpage、隐藏TabControl头部的选项卡等
7851 0
Winform控件优化之TabControl控件的使用和常用功能
|
SQL 关系型数据库 MySQL
将MySQL 数据迁移到 PostgreSQL
将MySQL 数据迁移到 PostgreSQL 可以采用以下步骤: 安装 PostgreSQL 数据库:首先,需要安装 PostgreSQL 数据库。可以从官方网站(https://www.postgresql.org/)下载最新版本的 PostgreSQL,并根据官方指南进行安装。 创建 PostgreSQL 数据库:在 PostgreSQL 中创建与 MySQL 数据库相对应的数据库。可以使用 pgAdmin 或命令行工具(如 psql)来创建数据库。例如,如果在 MySQL 中有一个名为 &quot;mydb&quot; 的数据库,那么可以在 PostgreSQL 中创建一个具有相同名称的数据库。 导
5299 0
|
消息中间件 Java 关系型数据库
10道不得不会的Docker面试题
10道不得不会的Docker面试题,10道不得不会的Docker面试题
9716 1
10道不得不会的Docker面试题
|
消息中间件 SQL 存储
超详细的RabbitMQ入门,看这篇就够了!
RabbitMQ入门,看这篇就够了
219724 69
|
域名解析 网络协议 安全
什么是DNS劫持攻击以及如何避免此类攻击
【10月更文挑战第28天】DNS劫持攻击是一种网络攻击方式,攻击者通过篡改用户的DNS设置,将合法网站的域名解析为恶意网站的IP地址,使用户在不知情的情况下访问钓鱼网站。攻击手段包括在用户系统植入恶意软件、利用路由器漏洞或破解DNS通信等。为防止此类攻击,应使用安全软件、定期检查DNS设置、重置路由器密码及避免访问不安全的网站。
1559 2
|
Java 网络安全
zookeeper的环境搭建和配置
本文介绍了如何在多台节点上搭建和配置Zookeeper环境。内容包括Zookeeper的下载、解压、环境变量配置、配置文件修改、zkdata目录创建、myid文件设置,以及将Zookeeper及其配置文件复制到其他节点。还提供了运行测试的命令,包括启动、状态检查和停止Zookeeper服务。
zookeeper的环境搭建和配置
|
10月前
|
机器学习/深度学习 数据可视化 算法
PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
神经常微分方程(Neural ODEs)是深度学习领域的创新模型,将神经网络的离散变换扩展为连续时间动力系统。本文基于Torchdyn库介绍Neural ODE的实现与训练方法,涵盖数据集构建、模型构建、基于PyTorch Lightning的训练及实验结果可视化等内容。Torchdyn支持多种数值求解算法和高级特性,适用于生成模型、时间序列分析等领域。
534 77
PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
|
XML JSON Ubuntu
Python实用记录(十五):PyQt/PySide6打包成exe,精简版(nuitka/pyinstaller/auto-py-to-exe)
本文介绍了使用Nuitka、PyInstaller和auto-py-to-exe三种工具将Python的PyQt/PySide6应用打包成exe文件的方法。提供了详细的安装步骤、打包命令和参数说明,适合新手学习和实践。
4862 0
|
Java 测试技术
【Java】已解决java.lang.UnsupportedOperationException异常
【Java】已解决java.lang.UnsupportedOperationException异常
2430 0
|
存储 机器学习/深度学习 人工智能
深入浅出 AI 智能体(AI Agent)|技术干货
随着人工智能技术的发展,智能体(AI Agents)逐渐成为人与大模型交互的主要方式。智能体能执行任务、解决问题,并提供个性化服务。其关键组成部分包括规划、记忆和工具使用,使交互更加高效、自然。智能体的应用涵盖专业领域问答、资讯整理、角色扮演等场景,极大地提升了用户体验与工作效率。借助智能体开发平台,用户可以轻松打造定制化AI应用,推动AI技术在各领域的广泛应用与深度融合。
31551 1