Java if / else alternative

klauskarambulut

Bekanntes Mitglied
Das ist ganz bestimmt nicht das wonach du gesucht hast.

Switch hat kaum vorteile gegenüber if-else.
Es ist gefährlich, wenn man den Fall-Through nicht beachtet.

Die Probleme die sich mit if-else ergeben sind, dass das selbe Konstrukt mehrmals in verschiedenen Kontexten verwendet wird.
Ein Beispiel zur Illustration Speisekarte
Zutatenliste
Java:
if(gericht.equals("Spaghetti")) {
  return "Nudeln, Tomaten, Hack";
} else if(gericht.equals("Pizza")) {
  return "Mehl, Tomaten, Käse";
} …

Preisliste
Java:
if(gericht.equals("Spaghetti")) {
  return 6;
} else if(gericht.equals("Pizza")) {
  return 7;
} …


Kommt ein neues Gericht hinzu, dann muß man jedes dieser Konstrukte erweitern sonst fehlt die Zutatenliste oder der Preis. Das ist das Fehleranfällige, da man nicht genau weiß, wo das ganze überall verwendet wird.

Die Lösung ist Polymorphie.
Man erstellt eine Klasse Gericht in der man alles Kapselt
Java:
class Gericht {
  String name;
  String zutaten;
  int preisInEuro;
  …
  public Gericht(String name, String zutaten, int preisInEuro) {
    this.name = name;
    this.zutaten = zutaten;
    this.preisInEuro;
  }
}

Dann hat man eine Factory die ein Gericht erstellt und dort benötigt man ein einzelnes switch case oder if-else Konstrukt das ein Gericht erstellt. (Alternativ kann man hier auch mit einer Map arbeiten, wenn man dann soweit ist)

Java:
if(gericht.equals("Spaghetti")) {
  return new Gericht("Spaghetti","Nudeln, Tomaten, Hack", 6);
} else if(gericht.equals("Pizza")) {
  return new Gericht("Pizza", "Mehl, Tomaten Käse", 7);
} …

An den Stellen an denen man dann die Zutaten haben möchte ruft man gericht.zutaten auf, an der Stelle für den Preis gericht.preisInEuro.

Will man etwas neues auf die Speisekarte tun, dann erweitert man nur das if-else ind der Factory um das weitere Gericht zu bekommen.
 
Zuletzt bearbeitet von einem Moderator:

Tobse

Top Contributor
Ich stimme @klauskarambulut zu: wenn ein If-Else-If Konstrukt zu unübersichtlich wird, ist es zu kompliziert und sollte vereinfacht werden; ggf. auch auf mehrere Klassen verteilt (selbstredend mit sauberer Trennung von Verantwortlichkeit).
 

nvidia

Bekanntes Mitglied
[...]
Die Lösung ist Polymorphie. [...]

Java:
if(gericht.equals("Spaghetti")) {
  return new Gericht("Spaghetti","Nudeln, Tomaten, Hack", 6);
} else if(gericht.equals("Pizza")) {
  return new Gericht("Pizza", "Mehl, Tomaten Käse", 7);
} …

[...]

Und dann? Dann kannst du nur mit der "Gericht"-Abstraktion arbeiten und es passiert das was immer passiert, man hat eine Menge von Gerichten und will z.B. nur für Pizzen und dann vll. auch nur ganz bestimmte den Preis erhöhen. Und schon ist man wieder bei den gleichen if-else-Kaskaden oder switches wie von dir beschrieben.
 

InfectedBytes

Top Contributor
da man nicht weiß wofür der TE das genau braucht, kann man hier eh nur mutmaßen.
Je nach Problem bietet es sich eben an switch zu benutzen oder eben nicht.
Falls der TE z.B. Werte einer enum prüfen will, ist switch meist die bessere wahl.
 
K

kneitzel

Gast
Also ich sehe da erst einmal die Polymorphie nicht in dem Beispiel. Polymorphie würde ja voraussetzen, das man mehrere Klassen hätte und dann die Factory eine entsprechende Instanz zurück gibt. Also neben der Klasse Gericht würde es dann noch Klassen wie "Spagetti" geben, die von Gericht erben. Aber mit nur einer einzelnen Klasse Gericht kann doch eigentlich nicht von Polymorphie gesprochen werden.

Und dieses Problem mit den Zutaten und Preis und so weiter ist doch auch etwas unrealistisch. Ich habe Datensätze "vom Typ" Gericht und die werden geladen. Egal ob durch Programmcode oder über eine Datenbank oder wie auch immer. Und dann arbeite ich da mit den Daten. Die Daten selbst in Klassen zu hinterlegen ist doch Wahnsinn, da dann gewisse Datenänderungen ja auch Änderungen am Code benötigen. Und bei diesen relativ trivialen Daten ist ein editieren im Code ja relativ unproblematisch. Und das lässt sich in einer GUI ja auch recht gut abbilden.
 

klauskarambulut

Bekanntes Mitglied
Das mit den Gerichten war ein einfaches Beispiel. Kann man gerne erweitern um die Polymorphie zu verdeutlichen.

Beim Gericht würde man nicht auf die Variablen direkt zugreifen sondern auf Accessoren, zum Beispiel Getter.
Das Könnte man nun ändern indem Gericht ein Interface wird und die bisherige Implementierung in BasisGericht geändert wird, das wiederum Gericht implementiert.
Code:
interface Gericht {
  String getName();
  String getZutaten();
  int getPreisInEuro();
}

BasisGericht sollte trivial sein, daher mal aussen vor.

So und jetzt machen wir daraus mal Gerichte zum mitnehmen
Code:
class ZumMitnehmen implements Gericht {
private Gericht gericht;
private static final int MITNAHME_AUFSCHLAG = 1;
  …
public Gericht(Gericht gericht){
   this.gericht = gericht;
}

  public String getName() {
    return gericht.getName() + " zum Mitnehmen";
  }

  public String getZutaten() {
    return gericht.getZutaten();
  }


  public int getPreisInEuro() {
    return preisInEuro + MITNAHME_AUFSCHLAG;
  }
}


Der einzige Code der sich ändert ist die Factory der Rest kann gleich bleiben.
 

Neue Themen


Oben