问题描述
这个问题的动机是我最近开始经常看到的东西,if..else if..else
结构.虽然它很简单,也有它的用途,但它的一些东西不断告诉我,它可以用更细粒度、更优雅且通常更容易保持最新的东西来代替.
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();
或使用 Map(在 Java 中,我也认为在 C# 中)或 Dictionary 或任何其他像这样的 K/V 结构:
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();
事实上,上面的 Map 方法是我上次最终做的,但现在我不能停止思考,对于这个确切的问题,总体上必须有更好的替代方案.
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.
那么,还有哪些替代 if..else if..else 的其他方法——而且很可能是更好的方法?你最喜欢哪一个?
So, which other -and most likely better- ways to replace the if..else if..else are out there and which one is your favorite?
好的,这是您的想法:
首先,最受欢迎的答案是 switch 语句,如下所示:
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;
}
这仅适用于可以在开关中使用的值,至少在 Java 中这是一个相当大的限制因素.当然,对于简单的情况也可以接受.
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.
您似乎建议的另一种可能更奇特的方法是使用多态来实现.CMS 链接的 Youtube 讲座是一个很好的手表,去这里看看:"The Clean Code Talks --继承、多态性和测试"据我所知,这将转化为这样的事情:
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();
Google 演讲中的两个有趣观点:
Two interesting points from the Google talk:
- 使用空对象而不是返回空值(并且请只抛出运行时异常)
- 尝试编写一个没有 if:s 的小项目.
另外一个在我看来值得一提的帖子是 CDR,他向我们提供了他的反常习惯,虽然不推荐使用,但看起来很有趣.
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.
这篇关于在程序中替换或替换 if..else if..else 树的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!