# Java if / else alternative



## Mr.Robot (24. Feb 2016)

Ich suche eine Alternative für die if / else Verzweigung, da diese nach einer Zeit unübersichtlich wird.

LG


----------



## JStein52 (24. Feb 2016)

Was meinst du mit "nach einiger Zeit" ? if/else ist nicht zeitabhängig 

Edit:  aber vielleicht meinst du ja auch switch/case


----------



## Xyz1 (24. Feb 2016)

Genau, switch case default wäre eine Alternative.


----------



## Mr.Robot (24. Feb 2016)

Danke, genau dannach habe ich gesucht!


----------



## klauskarambulut (24. Feb 2016)

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

```
if(gericht.equals("Spaghetti")) {
  return "Nudeln, Tomaten, Hack";
} else if(gericht.equals("Pizza")) {
  return "Mehl, Tomaten, Käse";
} …
```

Preisliste

```
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

```
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)


```
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.


----------



## Tobse (24. Feb 2016)

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 (25. Feb 2016)

klauskarambulut hat gesagt.:


> [...]
> Die Lösung ist Polymorphie. [...]
> 
> 
> ...



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 (25. Feb 2016)

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.


----------



## kneitzel (25. Feb 2016)

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.


----------



## JStein52 (25. Feb 2016)

InfectedBytes hat gesagt.:


> da man nicht weiß wofür der TE das genau braucht


Doch weiß man. Er hat ja gesagt er hat genau das gesucht


----------



## klauskarambulut (25. Feb 2016)

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.

```
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

```
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.


----------

