Этот вопрос мотивирован тем, что я в последнее время начал видеть слишком часто, структуру 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 и я думаю, что на С# тоже) или Словарь или любая другая структура 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 и какой из них ваш любимый?
Ваши мысли ниже этой строки!
Хорошо, вот ваши мысли:
Во-первых, самым популярным ответом был оператор switch, например:
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
Это работает только для значений, которые могут использоваться в коммутаторах, что, по крайней мере, в Java, является весьма ограничивающим фактором. Разумеется, приемлемо для простых случаев.
Другой и, возможно, немного более интересный способ, который, как вам кажется, заключается в том, чтобы сделать это, используя полиморфизм. Лекция Youtube, связанная с CMS, - отличные часы, посмотрите здесь: "Чистые коды кодов - наследование, полиморфизм и тестирование" Как насколько я понял, это переведет на что-то вроде этого:
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:
- Используйте Null Objects вместо того, чтобы возвращать null (и, пожалуйста, бросайте только Runtime Exceptions)
- Попробуйте написать небольшой проект, если: s.
Кроме того, на мой взгляд, стоит упомянуть CDR, который предоставил нам свои извращенные привычки, и, хотя он не рекомендуется использовать, очень интересно посмотреть.
Спасибо всем за ответы (пока), я думаю, что, возможно, сегодня что-то узнал!