Eine Navigation soll eine Route von A nach B berechnen.
Je nach Verkehrsmittel (Auto, Fahrrad, zu Fuß) läuft die Berechnung anders ab.
Naive Lösung:
Navigation enthält alle Berechnungsvarianten selbst undif/else anhand eines Strings aus, welche ausgeführt wirdpublic class Navigation {
public void route(String start, String ziel, String verkehrsmittel) {
if (verkehrsmittel.equals("auto")) {
System.out.println("Auto: " + start + " -> " + ziel + " über die Autobahn, ca. 25 Minuten");
} else if (verkehrsmittel.equals("fahrrad")) {
System.out.println("Fahrrad: " + start + " -> " + ziel + " über Radwege, ca. 50 Minuten");
} else if (verkehrsmittel.equals("fuss")) {
System.out.println("Zu Fuß: " + start + " -> " + ziel + " durch den Park, ca. 2 Stunden");
}
}
}
Problem damit:
Navigation wächst mit jedem neuen Verkehrsmittel (z. B. ÖPNV) weiter anNavigation selbst"fahrad") fallen erst zur Laufzeit aufRoutenstrategieNavigation hält nur noch eine Referenz auf eine Routenstrategie und delegiert die Berechnung an sieLosgelöst von der Navigation-Geschichte bleibt als abstrakte Schablone:
interface Strategie { ErgebnisTyp ausfuehren(EingabeTyp daten); }
class Kontext {
private Strategie strategie;
Kontext(Strategie s) {
this.strategie = s;
}
void setStrategie(Strategie s) {
this.strategie = s;
}
ErgebnisTyp arbeiten(EingabeTyp daten) {
return strategie.ausfuehren(daten);
}
}
Alles andere (Navigation/Route, Warenkorb/Bezahlart, Sortierer/Sortierverfahren …) ist nur austauschbares Vokabular über dieser Struktur.
Routenstrategie (Strategie-Interface)
berechneRoute(String start, String ziel), die jede konkrete Strategie implementieren mussNavigation (Kontext)
RoutenstrategiesetStrategie() wechselnroute() nur strategie.berechneRoute() auf – ohne if/elseAutoRoute, FahrradRoute, FussRoute (konkrete Strategien)
Routenstrategie und enthalten jeweils genau einen AlgorithmusMain)
new für die Strategien außerhalb von Navigation
Routenstrategie-Schnittstelleinterface Routenstrategie {
void berechneRoute(String start, String ziel);
}
class Navigation {
private Routenstrategie strategie;
public Navigation(Routenstrategie strategie) {
this.strategie = strategie;
}
public void setStrategie(Routenstrategie strategie) {
this.strategie = strategie;
}
public void route(String start, String ziel) {
strategie.berechneRoute(start, ziel);
}
}
class AutoRoute implements Routenstrategie {
public void berechneRoute(String start, String ziel) {
System.out.println("Auto: " + start + " -> " + ziel + " über die Autobahn, ca. 25 Minuten");
}
}
class FahrradRoute implements Routenstrategie {
public void berechneRoute(String start, String ziel) {
System.out.println("Fahrrad: " + start + " -> " + ziel + " über Radwege, ca. 50 Minuten");
}
}
class FussRoute implements Routenstrategie {
public void berechneRoute(String start, String ziel) {
System.out.println("Zu Fuß: " + start + " -> " + ziel + " durch den Park, ca. 2 Stunden");
}
}
public class Main {
public static void main(String[] args) {
Navigation navigation = new Navigation(new AutoRoute());
navigation.route("Alexanderplatz", "Wannsee");
navigation.setStrategie(new FahrradRoute());
navigation.route("Alexanderplatz", "Wannsee");
navigation.setStrategie(new FussRoute());
navigation.route("Alexanderplatz", "Wannsee");
}
}
Ausgabe:
Auto: Alexanderplatz -> Wannsee über die Autobahn, ca. 25 Minuten
Fahrrad: Alexanderplatz -> Wannsee über Radwege, ca. 50 Minuten
Zu Fuß: Alexanderplatz -> Wannsee durch den Park, ca. 2 Stunden
Dreimal derselbe Aufruf navigation.route(...) – das Ergebnis hängt nur davon ab, welche Strategie gerade gesetzt ist.
Vorteile:
if/switch-Ketten mehr im Kontext: Jeder Algorithmus steht in seiner eigenen, übersichtlichen Klasse.Navigation zu ändern (offen für Erweiterung, geschlossen für Modifikation).