在程序中取代或替代if...else的最佳方法是什么?[英] What is the best way to replace or substitute if..else if..else trees in programs?

本文是小编为大家收集整理的关于在程序中取代或替代if...else的最佳方法是什么?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

这个问题是由于我最近开始看到的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();

或使用映射(在Java中,我也认为在C#中)或字典或任何其他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();

实际上,上面的地图方法是我上次做的事情,但是现在我不能停止以为在这个确切问题上必须有更好的选择.

所以,哪些其他 - 最有可能替换if .. else if .. else在那里,哪个是您最喜欢的?

您的想法在这条线下!


好吧,这是您的想法:

首先,最受欢迎的答案是Switch语句,例如:

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

仅适用于可以在开关中使用的值,这至少在Java中是一个限制因素.但是,对于简单的情况可以接受,自然.

您似乎建议的另一种甚至更典型的方式是使用多态性做到这一点. CMS链接的YouTube讲座是一款出色的手表,请在此处查看:"干净的代码谈话 - 据我所知,继承,多态性和测试" 这将转化为这样的东西:

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 Talk中的两个有趣的观点:

  • 使用null对象而不是返回nulls(请仅投掷运行时异常)
  • 尝试编写一个没有:s.
  • 的小项目

此外,我认为值得一提的是CDR,他提供了与我们的不正当习惯,虽然不建议使用,但观看.

很有趣.

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

推荐答案

这些结构通常可以用多态性代替.这将为您提供更短且较少的脆性代码.

其他推荐答案

在面向对象的语言中,使用多态性替换为

是常见的

我喜欢这个涵盖该主题的Google Clean Code Talk:

干净的代码会谈 - 继承,多态性,测试

摘要

您的代码是否已满if语句? 切换语句?你有吗 在各种中相同的开关语句 地方?当您进行更改时 发现自己做出同样的改变 如果/切换几个 地方?你曾经忘记过一个吗?

本演讲将讨论 使用面向对象的技术 删除许多条件.这 结果更清洁,更紧密,更好 设计的代码易于测试, 理解和维护.

其他推荐答案

开关语句:

switch(i)
{
  case 1:
    doOne();
    break;

  case 2:
    doTwo();
    break;

  case 3:
    doThree();
    break;

  default:
    doNone();
    break;
}

本文地址:https://www.itbaoku.cn/post/627561.html

问题描述

This question is motivated by something I've lately started to see a bit too often, the if..else if..else structure. While it's simple and has its uses, something about it keeps telling me again and again that it could be substituted with something that's more fine-grained, elegant and just generally easier to keep up-to-date.

To be as specific as possible, this is what I mean:

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

I can think of two simple ways to rewrite that, either by ternary (which is just another way of writing the same structure):

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

or using Map (in Java and I think in C# too) or Dictionary or any other K/V structure like this:

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();

In fact the Map method above is what I ended up doing last time but now I can't stop thinking that there has to be better alternatives in general for this exact issue.

So, which other -and most likely better- ways to replace the if..else if..else are out there and which one is your favorite?

Your thoughts below this line!


Okay, here are your thoughts:

First, most popular answer was switch statement, like so:

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

That only works for values which can be used in switches, which at least in Java is quite a limiting a factor. Acceptable for simple cases though, naturally.

The other and perhaps a bit fancier way you seem to sugges is to do it using polymorphism. The Youtube lecture linked by CMS is an excellent watch, go see it here: "The Clean Code Talks -- Inheritance, Polymorphism, & Testing" As far as I understood, this would translate to something like this:

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();

Two interesting points from the Google talk:

  • Use Null Objects instead of returning nulls (and please throw only Runtime Exceptions)
  • Try to write a small project without if:s.

Also in addition one post worth mentioning in my opinion is CDR who provided his perverse habits with us and while not recommended to use, it's just very interesting to look at.

Thank you all for the answers (so far), I think I might have learned something today!

推荐答案

These constructs can often be replaced by polymorphism. This will give you shorter and less brittle code.

其他推荐答案

In Object Oriented languages, it's common to use polymorphism to replace if's.

I liked this Google Clean Code Talk that covers the subject:

The Clean Code Talks -- Inheritance, Polymorphism, & Testing

ABSTRACT

Is your code full of if statements? Switch statements? Do you have the same switch statement in various places? When you make changes do you find yourself making the same change to the same if/switch in several places? Did you ever forget one?

This talk will discuss approaches to using Object Oriented techniques to remove many of those conditionals. The result is cleaner, tighter, better designed code that's easier to test, understand and maintain.

其他推荐答案

A switch statement:

switch(i)
{
  case 1:
    doOne();
    break;

  case 2:
    doTwo();
    break;

  case 3:
    doThree();
    break;

  default:
    doNone();
    break;
}