Was ist der beste Weg zu ersetzen oder zu ersetzen, wenn ..else if..else Bäume in Programmen?

Diese Frage ist motiviert durch etwas, was ich in letzter Zeit begann zu sehen, ein bisschen zu oft, die if..else if..else Struktur. Es ist zwar einfach und hat auch seinen nutzen, etwas über es sagt mir immer wieder, dass es könnte ersetzt werden, mit etwas, das mehr ist feinkörnig, elegant und einfach in der Regel einfacher zu halten up-to-date.

So genau wie möglich, dies ist, was ich meine:

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

Ich denken kann, sind zwei einfache Möglichkeiten, um zu umschreiben, entweder durch ternäre (was nur eine andere Schreibweise der gleichen Struktur):

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

oder mit Karte (in Java, und ich denke in C#) oder Wörterbuch oder jede andere K/V Struktur wie dieser:

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 der Tat die Map-Methode, die oben ist, was ich am Ende tun die Letzte Zeit, aber jetzt ich kann nicht aufhören zu denken, dass es bessere alternativen im Allgemeinen für genau dieses Problem.

So, die anderen -und wahrscheinlich besser - Wege zu ersetzen, die if..else if..else draußen sind, und welches ist Ihr Favorit?

Ihre Gedanken unterhalb dieser Zeile!


Okay, hier sind Ihre Gedanken:

Erste, beliebteste Antwort war "switch" - Anweisung, etwa so:

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

Das funktioniert nur für Werte, die verwendet werden können in-Schalter, was zumindest in Java ist durchaus ein limitierender Faktor. Akzeptabel für einfache Fälle, obwohl, natürlich.

Den anderen und vielleicht etwas ausgefalleneren Art und Weise Sie scheinen zu sugges ist, es zu tun Polymorphismus. Die Youtube-Vorlesung verbunden, die von CMS ist eine hervorragende Uhr, gehen Sie sehen es hier: "The Clean Code Talks -- Vererbung, Polymorphismus, & - Prüfung" soweit ich das verstanden, würde dies übersetzen, so etwas wie dieses:

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

Zwei interessante Punkte aus dem Google-talk:

  • Null-Objekte, statt der Rückgabe von null-Werten (und bitte werfen Sie nur Runtime-Exceptions)
  • Versuchen zu schreiben, ein kleines Projekt ohne wenn:s.

Darüber hinaus auch einen Beitrag erwähnenswert ist meiner Meinung nach CDR, seine perversen Gewohnheiten mit uns, und zwar nicht empfohlen, um zu verwenden, es ist einfach sehr interessant zu Lesen.

Danke an Euch alle für die Antworten (bisher), ich glaube ich habe etwas gelernt heute!

InformationsquelleAutor der Frage Esko | 2009-02-06

Schreibe einen Kommentar