Switches ohne String

Mart

Top Contributor
Ich stehe shcon länger auf dem Schlauch wenn man zb navigiert hat man die Methode

Java:
void gehen(String richtung)
{
    if(richtung.equals("norden"))
        else if(richtung.equals("süden"))
}
das muss doch anders auch gehen ohne jedes mal einen String zu benutzen, bzw. etwas anderes zu benutzen ,ohne jedesmal die switch bzw die If else zu haben

sodass man basierend auf dem Übergabe parameter eine Methode ausführt
 

Robert Zenz

Bekanntes Mitglied
Ja und Nein. Geht es anders? Ja. Wird es viel simpler? Nein, nicht ganz.

Nehmen wir mal du hast einen Spieler und bewegst diesen in eine der vier Himmelsrichtungen:

Java:
public void gehen(String richtung) {
    if (richtung.equals("norden")) {
        splieler.position.y = splieler.position.y + 1;
    } else if (richtung.equals("sueden")) {
        splieler.position.y = splieler.position.y - 1;
    } else if (richtung.equals("westen")) {
        splieler.position.x = splieler.position.x - 1;
    } else if (richtung.equals("osten")) {
        splieler.position.x = splieler.position.x + 1;
    }
}

Das koennen wir jetzt natuerlich auf ein "switch" umbauen:

Java:
public void gehen(String richtung) {
    switch (richtung) {
        case "norden":
            splieler.position.y = splieler.position.y + 1;
            break;
      
        case "sueden":
            splieler.position.y = splieler.position.y - 1;
            break;
      
        case "westen":
            splieler.position.x = splieler.position.x - 1;
            break;
      
        case "osten":
            splieler.position.x = splieler.position.x + 1;
            break;
    }
}

So...macht die Sache jetzt nicht wirklich viel besser, um ehrlich zu sein. Naechster Schritte muesste eigentlich sein einen Enum zu verwenden.

Java:
public enum Himmelsrichtung {
    NORDEN,
    SUEDEN,
    WESTEN,
    OSTEN;
}

public void gehen(Himmelsrichtung richtung) {
    switch (richtung) {
        case NORDEN:
            splieler.position.y = splieler.position.y + 1;
            break;
      
        case SUEDEN:
            splieler.position.y = splieler.position.y - 1;
            break;
      
        case WESTEN:
            splieler.position.x = splieler.position.x - 1;
            break;
      
        case OSTEN:
            splieler.position.x = splieler.position.x + 1;
            break;
    }
}

Damit haben wir zumindest mal Typen-Sicherheit gewonnen und koennen nicht mehr so einfach Tippfehler mehr machen. Von hier aus wird es aber schwierig, weil die Logik muss irgendwie mit diesen Werten verbunden sein. Wir koennten zum Beispiel dem Enum beibringen den Spieler zu bewegen.

Java:
public enum Himmelsrichtung {
    NORDEN(0, +1),
    SUEDEN(0, -1),
    WESTEN(-1, 0),
    OSTEN(+1, 0);
  
    private int bewegung_x = 0;
    private int bewegung_y = 0;
  
    private Himmelsrichtung(int bewegung_x, int bewegung_y) {
        super();
      
        this.bewegung_x = bewegung_x;
        this.bewegung_y = bewegung_y;
    }
  
    public final void spielerBewegen(Spieler spieler) {
        splieler.position.x = splieler.position.x + bewegung_x;
        splieler.position.y = splieler.position.y + bewegung_y;
    }
}

public void gehen(Himmelsrichtung richtung) {
    richtung.spielerBewegen(spieler)
}

Gewinnen wir dadurch etwas? Nein, eigentlich nicht. Der Enum ist jetzt um einiges komplexer und ist noch dazu verbunden mit dem Spieler.

Wir koennten jetzt noch versuchen das ganze mit mehr Klassen zu loesen, aber ab hier wird es einfach nur komplexer ohne dass wir etwas gewinnen. Das "switch" (mit Enum) ist, meiner Meinung nach, das lesbarste das du in diesem Fall finden wirst. Irgendwo muss die Logik sein welche den Spieler um jeweils ein Feld bewegt, und mir persoenlich ist es lieber wenn dies in einer Funktion passiert, als ueber 2 verschiedene Klassen mit 4 Implementationen aufgeteilt ist.
 

Mart

Top Contributor
Java:
TextFileOperationExecutor textFileOperationExecutor
 = new TextFileOperationExecutor();
TextFile textFile = new TextFile("file1.txt");
textFileOperationExecutor.executeOperation(textFile::open);
textFileOperationExecutor.executeOperation(textFile::save);
basierend auf dem was im command pattern drin gestanden ist wäre es möglich sowas zu schreiben


Java:
void gehen(Richtung richtung){
    spieler.geh(bewegen::richtung)
}
also dass man die methode die man aufruft übergeben kann und basierend auf den das ausgeführt wird
 

Robert Zenz

Bekanntes Mitglied
Und jetzt noch ein ueberzuechtetes Beispiel, der Vollstaendigkeit halber:

Java:
public enum Himmelsrichtung {
    NORDEN,
    SUEDEN,
    WESTEN,
    OSTEN;
}

public interface SpielerAenderer {
    public abstract void anwenden(Spieler spieler);
}

public class GeheNachNordenSpielerAenderer implements SpielerAenderer {
    @Override
    public void anwenden(Spieler spieler) {
        spieler.position.y = spieler.position.y + 1
    }
}

public class GeheNachSuedenSpielerAenderer implements SpielerAenderer {
    @Override
    public void anwenden(Spieler spieler) {
        spieler.position.y = spieler.position.y - 1
    }
}

public class GeheNachWestenSpielerAenderer implements SpielerAenderer {
    @Override
    public void anwenden(Spieler spieler) {
        spieler.position.x = spieler.position.x - 1
    }
}

public class GeheNachOstenSpielerAenderer implements SpielerAenderer {
    @Override
    public void anwenden(Spieler spieler) {
        spieler.position.x = spieler.position.x + 1
    }
}

private Map<Himmelsrichtung, SpielerAenderer> bewegungen = new HashMap<>();
bewegungen.put(Himmelsrichtung.NORDEN, new GeheNachNordenSpielerAenderer());
bewegungen.put(Himmelsrichtung.SUEDEN, new GeheNachSuedenSpielerAenderer());
bewegungen.put(Himmelsrichtung.WESTEN, new GeheNachWestenSpielerAenderer());
bewegungen.put(Himmelsrichtung.OSTEN, new GeheNachOstenSpielerAenderer());

public void gehen(Himmelsrichtung richtung) {
    bewegungen.get(richtung).anwenden(spieler);
}

Und wir sehen...wir gewinnen nichts in diesem Fall...ganz im Gegenteil...
 

mrBrown

Super-Moderator
Mitarbeiter
Irgendwo muss die Logik sein welche den Spieler um jeweils ein Feld bewegt, und mir persoenlich ist es lieber wenn dies in einer Funktion passiert, als ueber 2 verschiedene Klassen mit 4 Implementationen aufgeteilt ist.
Die Logik besteht aktuell ja auch zwei Teilen: nächste Position bestimmen und Spieler dorthin bewegen (und auf Dauer sicherlich noch mehr, zB prüfen ob Bewegung möglich ist).

Das kann man grad mit dem Enum ziemlich sauber trennen: anstatt den Spieler übergibt man die Position und bekommt dann die neue Position zurück. Oder andersrum: die Position bekommt den enum und gibt die neue Position zurück.


Und wir sehen...wir gewinnen nichts in diesme Fall...ganz im Gegenteil...
Sowas würde deshalb auch jeder Refactoren, 4 identische Klassen nutzt dafür doch niemand ;)
 

Mart

Top Contributor
Sowas würde deshalb auch jeder Refactoren, 4 identische Klassen nutzt dafür doch niemand ;)
Wie meinst du das?

es geht im Moment eher um das Prinzip, wie man so eine Problematik anpacken sollte und nicht speziell um die Bewegung ,da diese als Beispiel gedacht war


in c# kann man das zb tun in dem Man in einem hash array eine Richtung und eine Function abspeichert und je nachdem welcher parameter gekommen ist die methode ausführt

nur ich weis nicht ob das der richtige weg ist methoden so abzurufen bzw wie man das in java machen sollte
 

Robert Zenz

Bekanntes Mitglied
Das kann man grad mit dem Enum ziemlich sauber trennen: anstatt den Spieler übergibt man die Position und bekommt dann die neue Position zurück. Oder andersrum: die Position bekommt den enum und gibt die neue Position zurück.
Du meinst sowas?

Java:
public enum Himmelsrichtung {
    NORDEN(0, +1),
    SUEDEN(0, -1),
    WESTEN(-1, 0),
    OSTEN(+1, 0);
  
    private int richtung_x = 0;
    private int richtung_y = 0;
  
    private Himmelsrichtung(int richtung_x, int richtung_y) {
        super();
      
        this.richtung_x = richtung_x;
        this.richtung_y = richtung_y;
    }
  
    public final void anwenden(Position position) {
        position.x = position.x + richtung_x;
        position.y = position.y + richtung_y;
    }
}

public void gehen(Himmelsrichtung richtung) {
    richtung.anwenden(spieler.position)
}

Mh, da koennte man vielleicht darueber reden, wirkt aber trotzdem immer noch nicht nach der wirklich guten Loesung.

es geht im Moment eher um das Prinzip, wie man so eine Problematik anpacken sollte und nicht speziell um die Bewegung ,da diese als Beispiel gedacht war
Allgemein kann man die Anforderung aber nicht beantworten, weil je nach dem auf was das "if" wirkt und welche Operationen dann passieren sollen, wird man etwas anderes brauchen. Das kann jetzt von meinem "switch" bis zu einer Plugin-Struktur alles sein.
 

Oneixee5

Top Contributor
Du könntest auch zu je Aktion ein Klasse, welche von Runable abgeleitet ist, in eine Map packen. Du kannst dann je nach Aktion das entsprechende Runable aus der Map holen und die Methode run aufrufen. Dabei sollte auch eine Default-Implemetierung erstellt werden, falls mal eine unbekannte Aktion aufgerufen wird. Das erspart die Verzweigung über if. Ob sich das jetzt für 4 Himmelsrichtungen lohnt sei dahingestellt.
 

mrBrown

Super-Moderator
Mitarbeiter
es geht im Moment eher um das Prinzip, wie man so eine Problematik anpacken sollte und nicht speziell um die Bewegung ,da diese als Beispiel gedacht war
Grundsätzlich hast du zwei verschiedene Möglichkeitem: den direkten Weg (mit if/switch/Map/...) oder Command Pattern. Letzteres ist oft „schöner“ und uU später einfacher zu nutzen, wenn auch initial etwas mehr Aufwand.

In beiden Umsetzungen kannst du dir dann überlegen, wie du das konkret geforderte umsetzt: trennt man Aktion und das Drumherum (hierbei Bewegen und nächste Position bestimmen) und wenn ja, wer hat die Verantwortlichkeiten für die einzelnen Dinge. Vor- und Nachteile kann man in fast jedem finden, die muss man dann für den konkreten Fall immer abwägen, und dafür kennt man am besten möglichst viele konkrete Anforderungen :)


Meine Präferenz wäre in diesem Fall Command Pattern, und Positionsberechnung rausgezogen in die Position und einen Enum für die Richtung - Möglichkeiten gibt es aber viele.
 

Mart

Top Contributor
Ok gut danke an alle

das muss ich mal alles in Ruhe durch den Kopf gehen lassen bis ich die ganzen sachen angesehen hab
 

kneitzel

Top Contributor
Unter dem Strich kommt alles auf das Gleiche hinaus:

Du hast Methoden für jede Aktion. Diese sind - je nach Umfang/Komplexität sinnvoller Weise Klassen, aber das ist egal.

Und nun musst Du diese aufrufen. Dies kannst Du viele unterschiedliche Wege machen.
- Du machst ein switch / case und rufst es dann auf.
- Du holst es aus einer Map und rufst es auf.
- Du hast bereits ein Enum und rufst da einfach eine Methode auf (NORDEN.execute(whatever))
- Oder das Enum hat (ähnlich der map) eine entsprechende Action hinterlegt (NORDEN.getAction().execute(whatever))
- oder ...

Aber bei allem sparst Du nicht wirklich was. Ich bin ein Enum Fetischist - Ich mag es, enums auch mal einiges mitzugeben an Funktionalität.
 

Oneixee5

Top Contributor
Es geht ja auch um die Grundprinzipen wie man das lösen kann zu sehen und nicht speziell über die Richtungen das war nur als Beispiel gedacht wozu jeder was anfangen könnte
Dazu noch ein kleines Beispiel

Java:
public final class Main {

    private enum Himmelsrichtung {
        NORDEN, SUEDEN, WESTEN, OSTEN, TO_HELL;
    }

    private static final Map<Himmelsrichtung, Runnable> actions;
    static {
        final EnumMap<Himmelsrichtung, Runnable> a = new EnumMap<>(Himmelsrichtung.class);
        a.put(Himmelsrichtung.NORDEN, (Runnable) () -> System.out.println("geh nach Norden"));
        a.put(Himmelsrichtung.SUEDEN, (Runnable) () -> System.out.println("geh nach Süden"));
        a.put(Himmelsrichtung.WESTEN, (Runnable) () -> System.out.println("geh nach Westen"));
        a.put(Himmelsrichtung.OSTEN, (Runnable) () -> System.out.println("geh nach Osten"));
        actions = Collections.unmodifiableMap(a);
    }

    public static void main(final String[] args) {

        gehen(Himmelsrichtung.NORDEN);
        gehen(Himmelsrichtung.WESTEN);
        gehen(Himmelsrichtung.TO_HELL);

    }

    private static void gehen(final Himmelsrichtung himmelsrichtung) {
        actions.getOrDefault(himmelsrichtung, (Runnable) () -> { throw new IllegalArgumentException(); }).run();
    }

}
Edit: Die cast's sind nicht nötig, die hat nur die IDE gemacht und sind jetzt übbrig - weil ich fast alles auf die Schnelle generiert habe.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Mozart53 JLabel nur meinen Text verschieben ohne Image Allgemeine Java-Themen 3
F Java JDK ohne Oracle Konto Allgemeine Java-Themen 5
H Matrix ohne Array erstellen Allgemeine Java-Themen 9
N E-Mail Validator (ohne Regex!) Allgemeine Java-Themen 7
A Java ListNode Element einfügen ohne Bibliothek Allgemeine Java-Themen 6
G Datei aus Ordner wählen, ohne den Dateinamen im Pfad angeben zu müssen Allgemeine Java-Themen 4
Thallius Zeitzone zu einem LocalDate hinzufügen aber ohne es zu ändern... Allgemeine Java-Themen 2
O Produziert das Tool "jpackage" (ab JDK 14) .exe Dateien, die auf einer Zielumgebung ohne JRE lauffähig sind ?` Allgemeine Java-Themen 7
Drachenbauer wie kann ich alle instanzen einer Klasse durchsehen, ohne, dass diese in einer Liste erzeugt wurden? Allgemeine Java-Themen 11
X Adjazenzliste ohne ArrayList Allgemeine Java-Themen 6
N Keylistener ohne Dazugehörige Gui Allgemeine Java-Themen 6
P Input/Output entfernte Datei mit Java öffnen ohne Download Allgemeine Java-Themen 5
Kirby.exe Keyboard Input ohne Enter Allgemeine Java-Themen 43
T Abgeleitetes Interface public ohne Schlüsselwort "interface"? Allgemeine Java-Themen 3
S Potenzieren mit rationalen Potenzen ohne Math.pow Allgemeine Java-Themen 16
F Timestamp in Oracle ohne Formatierung reinbekommen Allgemeine Java-Themen 7
M Drucken ohne Dialog Allgemeine Java-Themen 1
L Operatoren Java Reflections: Alle Methoden einer Klasse aufrufen ohne Exceptions Allgemeine Java-Themen 5
J .java-Dateitext Compile zur Laufzeit ohne File Allgemeine Java-Themen 15
O Zugriff auf mySQL ohne JDBC Allgemeine Java-Themen 3
S Input/Output Jave.utill.logging ohne Default-Locale also in Englisch Allgemeine Java-Themen 3
J ftp - delete file ohne appache Allgemeine Java-Themen 8
H float Berechnung: Ergebnis ohne wissenschaftliche Notation Allgemeine Java-Themen 5
offi Excel mit Inhalten aus DB öffnen ohne zu speichern Allgemeine Java-Themen 8
E String in Zahl umwandeln, ohne Befehl Integer.parseInt Allgemeine Java-Themen 3
S Java Plugin System (ohne OSGI) Allgemeine Java-Themen 10
G Array ohne Aufzählungszeichen ausgeben Allgemeine Java-Themen 6
Aruetiise Swing JOptionPane ohne denn Thread zu pausieren Allgemeine Java-Themen 1
RalleYTN Audiolänge einer MP3 Datei erhalten ohne diese vollständig zu laden Allgemeine Java-Themen 15
RalleYTN 2D-Grafik Bild ohne AWT, Swing und JavaFX rotieren Allgemeine Java-Themen 12
A BufferedReader ohne System.in Allgemeine Java-Themen 9
E Programm ohne Windowsrand(Vollbild) ? Allgemeine Java-Themen 5
B Applikation ohne (direkt)Java installiert zu haben auszuführen Allgemeine Java-Themen 8
RalleYTN Datentypen Herausfinden ob Object ein Array ist ohne den Typen des Arrays zu kennen? Allgemeine Java-Themen 12
NicoDeluxe JavaMail ohne Anhang senden Allgemeine Java-Themen 4
N String ins Clipboard kopieren ohne makieren. Allgemeine Java-Themen 12
T Ziffernsumme ohne String Operatoren Allgemeine Java-Themen 4
E Threads Ausführung in Threads ist langsamer als ohne Threads Allgemeine Java-Themen 13
R NullPointerException Ohne Grund Allgemeine Java-Themen 5
RalleYTN JPEG mit CMYK(ohne JAI oder TwelveMonkeys!) Allgemeine Java-Themen 0
P Zwei ArrayLists: Ohne die eine überhaupt anzurühren, wird sie verändert Allgemeine Java-Themen 2
HarleyDavidson Input/Output Heruntergeladene Datei direkt nach dem Download öffnen ohne zu speichern Allgemeine Java-Themen 1
Y String to Double ohne ParseDouble Allgemeine Java-Themen 11
S Methoden ohne Methodenkopf ?! Allgemeine Java-Themen 5
L Daten ohne Datenbank richtig abspeichern Allgemeine Java-Themen 5
A Linux: Native Library mit Rootrechten ohne Prozess mit sudo zu starten Allgemeine Java-Themen 1
T Threads Input/Output im Thread - Datei ohne Inhalt Allgemeine Java-Themen 1
A Konstrukt ohne Main für Xml-Parser Allgemeine Java-Themen 1
S Performante Visualisierung groẞer Datenmengen (ohne JFreeChart) Allgemeine Java-Themen 22
M Permutation ohne Wiederholung mit rekursion Allgemeine Java-Themen 4
C HtmlUnit Daten einer Tabelle bekommen ohne, dass diese eine ID aufweist Allgemeine Java-Themen 1
F File.listFiles ohne .sort Allgemeine Java-Themen 6
H Unicode ausgeben ohne Umwandlung - geht das? Allgemeine Java-Themen 3
L iText PDF-Generierung ohne Speichern Allgemeine Java-Themen 10
R Wie schaffe ich es, dass java zB 100 zählt ohne ständig "else if" hinschreiben zu müssen? Allgemeine Java-Themen 7
T Zwei Wortendungen vergleichen ohne .equals Allgemeine Java-Themen 10
J Array ohne vorher festgelegte Länge oder Wie wandle ich Zahlen in Zahlen mit anderen Basen um? Allgemeine Java-Themen 6
M Werte aus DB in Liste speichern ohne mehrfach speicherung Allgemeine Java-Themen 15
T Programm bleibt ohne Fehler stehen Allgemeine Java-Themen 4
J log4j ohne propertiedatei Allgemeine Java-Themen 4
D Classloader ohne Package Allgemeine Java-Themen 10
A Collections Array-Elemente in ArrayList kopieren ohne Schleife Allgemeine Java-Themen 7
K print() geht nicht ohne println() Allgemeine Java-Themen 3
S KeyListener ohne Focus - Wie? Allgemeine Java-Themen 2
Rudolf JUnit4-Testklasse erweitern ohne zu vererben Allgemeine Java-Themen 6
W Passwort Clientseitig sicher ablegen ohne Hash Allgemeine Java-Themen 2
S Antlr Grammatik übersetzt ohne Fehler, dennoch wird Zahl nicht als Eingabe erkannt Allgemeine Java-Themen 4
A Java ohne Java-Installation? Allgemeine Java-Themen 5
H Apache POI HSSF - Farbe/Rahmen etc. ohne Style-Vorlage? Allgemeine Java-Themen 4
E KeyListener ohne GUI Allgemeine Java-Themen 6
Guybrush Threepwood Pattern gesucht: Punkt ohne Leerzeichen dahinter Allgemeine Java-Themen 3
S Entfernen von allen Nicht-Buchstaben chars aus einem String ohne Regex..? Allgemeine Java-Themen 10
K Vererbung ohne Basisklasse zu kennen Allgemeine Java-Themen 20
B File umbennen ohne Extension zu aendern Allgemeine Java-Themen 2
J Laden von JAR Files geht ohne ADMIN Rechte sehr langsam Allgemeine Java-Themen 6
A Methoden ohne Referenzen finden Allgemeine Java-Themen 9
P Tastatur abfrage ohne KeyListener Allgemeine Java-Themen 3
L JAR verändern - JAVAC soll einfach nur kompilieren, ohne Prüfungen Allgemeine Java-Themen 16
S auf public void Methode zugreifen ohne static Allgemeine Java-Themen 11
N Guice - Ohne injector.getInstance Allgemeine Java-Themen 2
S Datei aus zip öffnen ohne zip zu entpacken Allgemeine Java-Themen 4
J Rechtsverschiebung OHNE Vorzeichenerweiterung Allgemeine Java-Themen 2
R Input/Output Objekte speichern ohne überschreiben Allgemeine Java-Themen 7
T Pascalsches Dreieck ohne array und rekursion Allgemeine Java-Themen 9
S Strg+V ohne Fokus simulieren! Allgemeine Java-Themen 12
T String in Date parsen (*ohne* bekanntes Format) Allgemeine Java-Themen 8
S Wörter ohne Leerzeichen erkennen Allgemeine Java-Themen 5
W Input/Output Drucken ohne GUI Allgemeine Java-Themen 11
M Klassen Zugriff auf getMethode ohne Klasse zu erzeugen Allgemeine Java-Themen 6
Kr0e Reflection - Instanz einer Klasse erstellen, ohne Default-Constructor Allgemeine Java-Themen 15
B NullPointerException ohne Angabe Allgemeine Java-Themen 5
P Threads Thread innerhalb einer Klasse - ohne Extra Klasse Allgemeine Java-Themen 9
T Firefox und Webstart: Ohne JNLP Download Allgemeine Java-Themen 2
F Multidimensionales Array ohne linare Reihenfolge! Allgemeine Java-Themen 8
C Regex: Zahl ohne führende Null Allgemeine Java-Themen 13
S Datum vergleichen - ohne Hilfsmittel Allgemeine Java-Themen 8
J xlsx Dateien lesen OHNE apache POI Allgemeine Java-Themen 6
M tar archive verarbeiten ohne zu entpacken Allgemeine Java-Themen 3
D Datei lesen ohne sie für umbenennen/verschieben zu sperren Allgemeine Java-Themen 13
P Listener für Tastatureingaben ohne Focus Allgemeine Java-Themen 4

Ähnliche Java Themen


Oben