在程序中替换 if..else if..else 树的最佳方法是什么?

2024-01-09

这个问题是由我最近开始经常看到的事情引起的,if..else if..else结构。虽然它很简单并且有它的用途,但它的一些东西一遍又一遍地告诉我,它可以被更细粒度、更优雅并且通常更容易保持最新的东西所取代。

尽可能具体,这就是我的意思:

if (i == 1) {
    doOne();
} else if (i == 2) {
    doTwo();
} else if (i == 3) {
    doThree();
} else {
    doNone();
}

我可以想到两种简单的方法来重写它,或者通过三元(这只是编写相同结构的另一种方法):

(i == 1) ? doOne() : 
(i == 2) ? doTwo() :
(i == 3) ? doThree() : doNone();

或使用 Map(在 Java 中,我认为也在 C# 中)或 Dictionary 或任何其他 K/V 结构,如下所示:

public interface IFunctor() {
    void call();
}

public class OneFunctor implemets IFunctor() {
    void call() {
        ref.doOne();
    }
}

/* etc. */    

Map<Integer, IFunctor> methods = new HashMap<Integer, IFunctor>();
methods.put(1, new OneFunctor());
methods.put(2, new TwoFunctor());
methods.put(3, new ThreeFunctor());
/* .. */
(methods.get(i) != null) ? methods.get(i).call() : doNone();

事实上,上面的 Map 方法是我上次所做的,但现在我无法停止思考,对于这个确切的问题,一般必须有更好的替代方法。

那么,还有哪些其他(而且很可能是更好的)方法来替代 if..else if..else,您最喜欢哪一种?

你的想法就在这条线下面!


好的,这是your想法:

首先,最受欢迎的答案是 switch 语句,如下所示:

switch (i) {
    case 1:  doOne(); break;
    case 2:  doTwo(); break;
    case 3:  doThree(); break;
    default: doNone(); break;
}

这仅适用于可在开关中使用的值,这至少在 Java 中是一个相当大的限制因素。当然,对于简单的情况来说是可以接受的。

您似乎建议的另一种也许更奇特的方法是使用多态性来实现。 CMS 链接的 Youtube 讲座非常精彩,请在这里观看:《整洁代码讲座——继承、多态性和测试》 http://www.youtube.com/watch?v=4F72VULWFvc据我了解,这将转化为这样的内容:

public interface Doer {
    void do();
}

public class OneDoer implements Doer {
    public void do() {
        doOne();
    }
}
/* etc. */

/* some method of dependency injection like Factory: */
public class DoerFactory() {
    public static Doer getDoer(int i) {
        switch (i) {
            case 1: return new OneDoer();
            case 2: return new TwoDoer();
            case 3: return new ThreeDoer();
            default: return new NoneDoer();
        }
    }
}

/* in actual code */

Doer operation = DoerFactory.getDoer(i);
operation.do();

Google 演讲中有两个有趣的观点:

  • 使用空对象而不是返回空值(并且请仅抛出运行时异常)
  • 尝试编写一个没有 if:s 的小项目。

另外,我认为值得一提的一个帖子是 CDR,他向我们提供了他的不正当习惯,虽然不建议使用,但看起来非常有趣。

谢谢大家的回答(到目前为止),我想我今天可能学到了一些东西!


这些结构通常可以被多态性取代。这将为您提供更短、更不易损坏的代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在程序中替换 if..else if..else 树的最佳方法是什么? 的相关文章

  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • 获取Windows下新线程/删除线程的通知

    创建 DLL 时 您可以在 DllMain 函数 DLL THREAD ATTACH DLL THREAD DETACH 中获取有关新线程 退出线程的通知 有没有办法在 非托管 可执行文件中从 Windows 获取这些或等效通知 是的 在您
  • Scala 功能设计模式目录

    一周以来我一直在阅读 Scala 编程 作者一步一步地介绍了该语言的元素 但我仍然很困惑何时使用演员 闭包 柯里化等功能性的东西 我正在寻找功能结构的典型用例或最佳实践的目录 我并不是说在 Scala 中重新实现像 GoF 这样的众所周知的
  • 承诺的反面是什么?

    承诺代表将来可能可用 或无法实现 的值 我正在寻找的是一种数据类型 它表示将来可能变得不可用的可用值 可能是由于错误 Promise a b TransitionFromTo
  • 有向无环图的人类可读文本表示

    一棵树有一堆人类和机器可读的文本表示 例如嵌套列表 以各种表示形式 例如 JSON 和 YAML 和 XML 与缩进相结合 它们使我们很容易想象得到的结构 但我没有看到任何具有相同水平可读性的东西有向无环图 https en wikiped
  • 池和集群之间的区别

    从最纯粹的角度来看 它们感觉像是相同的概念 两者都管理资源 节点集并控制来自外部组件或由外部组件进行的访问 通过池 您可以向池借用这些资源 节点 也可以从池中归还这些资源 节点 对于集群 您在资源 节点前面有一个负载均衡器 并且您可以向负载
  • Android:单一活动,多个视图

    我不是 Android 专业人士 尽管我开发了一个包含 50 多个活动的应用程序 这使得该应用程序非常庞大 经过8周的开发 现在出现了一些问题 导致应用程序难以维护和升级 我正在处理的主要问题是 我无法将对象引用传递给活动的构造函数 事实上
  • 是否可以证明序列是否是随机的?

    考虑以下输入 1 1 2 3 5 8 这不是随机的 2 4 8 16 32 这都不是 4 1 2 11 5 9 这个看起来像随机序列 我想问是否有这样的算法来证明输入是否是随机的 不 没有这样的证明 如果你有完全随机的数字 则每个长度为 n
  • 这个单例能够抵抗序列化和反射攻击吗?

    以下代码是否能够抵抗序列化和反射攻击 public class Example private static Example instance new Example private Example public static Exampl
  • 线性模式匹配算法?

    我有一个由 0 和 1 组成的线性列表 我需要匹配多个简单模式并找到第一个出现的情况 例如 我可能需要找到0001101101 01010100100 OR 10100100010长度为 800 万的列表内 我只需要找到第一次出现的情况 然
  • 使用对象列表构建树

    我有一个带有属性 id 和parent id 的对象列表 我想建造一棵树来连接那些孩子和父母 1 个父对象可以有多个子对象 并且有一个对象将成为所有对象的祖先 实现该功能最快的算法是什么 我使用 C 作为编程语言 但其他语言也可以 像这样的
  • 什么是 NOR 逻辑运算符?

    Is nor a 或 b a 或 b a 和 b 还有什么吗 a 或 b see http en wikipedia org wiki Logical NOR http en wikipedia org wiki Logical NOR了解
  • REST API 登录模式

    我正在创建一个 REST api 严格遵循 apigee 建议 使用名词而不是动词 将 api 版本烘焙到 URL 中 每个集合有两个 api 路径 GET POST PUT DELETE 用法等 我正在开发登录系统 但不确定登录用户的正确
  • F#:模式构成?

    我正在尝试编写一个由另外两个模式组成的模式 但我不确定如何去做 我的输入是字符串列表 文档 我有一个与文档标题匹配的模式和一个与文档正文匹配的模式 该模式应该匹配整个文档并返回标题和正文模式的结果 您可以使用以下命令一起运行两个模式 您在问
  • 如何在C++中正确实现工厂方法模式

    C 中有这样一件事让我在很长一段时间内感到不舒服 因为老实说我不知道 该怎么做 尽管它听起来很简单 如何在 C 中正确实现工厂方法 目标 允许客户端使用工厂方法而不是对象的构造函数来实例化某个对象 而不会产生不可接受的后果和性能影响 我所说
  • Java:getInstance 与静态

    目的是什么getInstance 在Java中 在我的研究过程中我一直在读getInstance 有助于实现单例设计模式 根据我的理解 这意味着整个程序中只有一个实例 但我不能只使用静态吗 这不是静态的全部意义吗 如果我只有静态方法和字段
  • 如何制作抗崩溃的ios应用程序

    我现在正在编写 ios 应用程序一段时间 但我的应用程序仍然经常崩溃 并且需要时间才能使它们变得非常稳定 我觉得这很烦人 那么 有没有关于防崩溃编程ios应用程序的编程模式呢 打开编译器警告 删除所有警告 运行静态分析器 删除所有警告 使用
  • 用于将 cython 中的许多 C++ 类包装到单个共享对象的项目结构

    我在文档 邮件列表和这个问题在这里 https stackoverflow com questions 10300660 cython and distutils 但我想得到一个更直接的答案来解决我的具体情况 我正在通过尝试一点一点地包装我
  • 使用什么算法来确定使系统达到“零”状态所需的最小操作数?

    这是一种更通用的问题 不是特定于语言的 有关要使用的想法和算法的更多信息 系统如下 它登记朋友群体之间的小额贷款 Alice and Bill要去吃午饭 比尔的卡坏了 所以爱丽丝支付了他的餐费 10 美元 第二天Bill and Charl
  • 奖励*完整*初学者的代码项目[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 为刚接触编程的人提供的课程通常包括一个代码项目 我认为这是一种很好的学习方式 然而 这样的项目往往让人感觉过于做作 因此做起来并没有多大回

随机推荐

  • 从 Liquid 数组中获取下一个和上一个元素

    简洁版本 我想将 1 添加到液体模板中的数字并将结果用作数组索引 capture plus one 0 plus 1 endcapture div Value of plus one plus one div div This works
  • PropTypes 在 React 中不起作用

    我正在运行 React 16 2 0 并且正在使用 PropTypes 15 6 1 我正在使用 ES6 语法和 Webpack 我试图让 PropTypes 在传递无效道具时发出警告 但它不起作用 这是代码 SimpleMessage j
  • 在 R Shiny 中读取文件

    因此 我正在 R闪亮中构建一个应用程序 要求用户上传 csv 文件 一旦被 R闪亮读入 我不确定如何实际操作该对象来使用 一般代码语法如下 用户界面文件 ui R Define UI for random distribution appl
  • 如何在 64 位 Windows 7 计算机上安装 pycrypto?

    我尝试使用安装 PyCryptopip 但它抱怨需要 vcvarsall bat 我安装了 Visual Studio 2008 但现在我得到了ValueError u path 当我尝试从安装它时pip 我尝试从下载预构建的二进制文件虚空
  • 当我从应用程序中清除数据时,Sqlite 数据库被删除

    我创造了Sqlite应用程序中的数据库 当我清除数据时settings gt applications gt manage applications the Sqlite数据库已删除 任何要保留的建议sqlite数据库原样 当您按下Clea
  • 为什么 IE11 错误地处理 Node.normalize() 的减号?

    我遇到了一个问题 即当使用 Node normalize 函数连接相邻文本节点时 具有某些字符的 DOM 文本节点在 IE 中表现得很奇怪 我创建了一个 Codepen 示例 它允许您在 IE11 中重现该错误 http codepen i
  • 从谷歌应用程序脚本预填写谷歌表单

    我有一份学生登记表 其中有学生证 这是必填字段 我有一个谷歌应用程序脚本函数 可以告诉该学生是否注册了任何课程 有没有办法通过调用 Google Apps 脚本函数 是 或 否 来自动填写注册的现场课程 是的 您可以使用表单 ID 创建预填
  • 有没有办法有条件地应用注释?

    在我的 java play 应用程序中 我有注释 RequiresAuthentication clientName CasClient 在我的控制器内 我只想在生产环境中对用户进行身份验证 如何有条件地应用注释 如果我处理身份验证的方式是
  • 在 as3 中获取对象值的最快方法

    好吧 我发誓这个问题应该无处不在 但事实并非如此 我有一个值对象 里面有很多 getter setter 它不是一个动态类 我迫切需要搜索充满它们的 ArrayCollection 搜索涵盖所有领域 因此我将使用大约 13 种不同类型的 V
  • 测试带有浮点数的元组的断言

    我有一个函数返回一个元组 其中包含一个浮点值 通常我使用assertAlmostEquals比较它们 但这不适用于元组 此外 元组还包含其他数据类型 目前 我正在单独断言元组的每个元素 但这对于此类元组的列表来说太多了 对于这种情况 有什么
  • 如何让 JavaScript 随着时间的推移(而不是立即)写入结果?

    我有一个程序 它会写入很多 if 结果 例如 这个 const a prompt for let i 1 i lt a i console log i 不是实际的代码 因此 当您输入一个大数字时 会有大量答案等待输入控制台 因此 当达到某个
  • Pandas - 如何检查多索引列是否存在

    我的问题类似于如何检查 Pandas 中是否存在列 https stackoverflow com questions 24870306 how to check if a column exists in pandas但对于多索引列的情况
  • 当我尝试首先使用 EF5 代码对数据库进行逆向工程时出现异常

    该视频向我展示了如何从现有数据库使用 Code First http msdn microsoft com en us data jj572367 http msdn microsoft com en us data jj572367 所以
  • 如何从 scala play 访问发布数据?

    我有一条类型为 POST 的路线 我正在将发布数据发送到页面 我如何访问该帖子数据 例如 在 PHP 中您使用 POST 如何访问 scala 和 play 框架中的发布数据 从 Play 2 1 开始 有两种方法获取 POST 参数 1
  • Google 应用程序引擎示例应用程序抛出 503

    我已经设置了 Google 应用引擎的示例 android本教程 https developers google com cloud samples mbs getting started 当我在 EditText 中输入内容并按发送按钮时
  • 手工滚动 SOAP 请求

    我正在尝试构建一个手动 HTTP 请求 以便从我认为相当简单的 SOAP Web 服务调用返回响应 但是 我在正确构建请求时遇到了困难 并且没有得到我期望的响应 适用的wsdl声明 wsdl 目标命名空间 targetNamespace h
  • 如何更改 FullCalendar 中选定日期的背景颜色

    我正在尝试更改日历中所选日期的背景颜色 在我的下面的代码中 它突出显示所有点击的日期 我怎样才能只突出显示最后点击的日期 dayClick function day var mydate new Date this 0 getAttribu
  • 将时间序列中的分类列扩展到多个每秒计数列

    进行以下转变的最佳方式是什么 此转换分为两个部分 第一个是将速度转换为每秒平均值 第二种方法是获取分类列并将其转换为多列 每个分类值一列 其中该值是每秒发生的次数 例如 输入 xts A Time PosixCT Observed Lett
  • 使用 Javascript Regex 将字符换行到字符串中,不包括链接标签

    EDIT 这就是我必须做的 想象一下 如果我有一个文本 里面有一些 html 标签 它仍然是一个字符串 var string p Hello my name is Mauricio p p Hi my name is Patricia p
  • 在程序中替换 if..else if..else 树的最佳方法是什么?

    这个问题是由我最近开始经常看到的事情引起的 if else if else结构 虽然它很简单并且有它的用途 但它的一些东西一遍又一遍地告诉我 它可以被更细粒度 更优雅并且通常更容易保持最新的东西所取代 尽可能具体 这就是我的意思 if i