2016-05-13 10 views
4

Ich habe die folgende Methode:Gesetz des Demeter - mit nur einem Punkt, könnte ich diese Logik verbessern?

private boolean reserveSeat(int selectedRow, int selectedSeat) { 
    if (show.getRows().get(selectedRow).getSeats().get(selectedSeat).getReservationStatus()) { 
     return false; 
    } else { 
     show.getRows().get(selectedRow).getSeats().get(selectedSeat).reserve(); 
     setRowNumber(selectedRow); 
     setSeatNumber(selectedSeat); 

     return true; 
    } 
} 

, die in einer Reservation Klasse befindet. Diese Klasse hat ein Show-Objekt (show), Eine Show hat Rows (ein anderes Objekt), Rows have Seats (ein anderes Objekt).

Meine Frage ist, könnte diese Methode verbessert werden? Ich habe über LoD gelesen und bin besorgt, dass mein Punkt ein schlechtes Design signalisiert, obwohl ich denke, dass es logisch ist. Es ist das Sitzobjekt, das weiß, ob es reserviert ist oder nicht. Aber geht es von Show zu Seat mit Fremden? oder ist es ok, weil jedes Objekt das nächste Objekt enthält?

Entschuldigung, wenn meine Suche nicht klar ist. Was scheint mit mir zu passieren (wahrscheinlich, weil ich Autodidakt bin) ist ich Design-Sachen, die funktioniert dann lese ich einige OOP-Design-Prinzipien und denke Mist, es funktioniert, aber es ist nicht gutes Design!

Jeder Ratschlag geschätzt.

+0

Sie könnten eine 'getRow' Methode erstellen, die' getRows tut(). Get (row) 'in der Show-Klasse. und ähnlich eine 'getSeat (seat)' Methode in Ihrer Zeilenklasse. Sie könnten sogar eine Hilfsmethode in Ihrer Show-Klasse hinzufügen: 'show.getSeat (row, seat)'. – assylias

+0

@assylias danke für die Antwort. getRows befindet sich derzeit in meiner Show-Klasse (und getSeat befindet sich derzeit in meiner Row-Klasse), aber ich denke, Sie sollten das getRows(). get (row) -Bit verwenden, damit dies in meiner Reservierungsklasse nicht gemacht wird Sinn. Eine Hilfsmethode wäre eine gute Idee –

Antwort

3

Ja, diese Kette von Anrufen ist viel zu lang. Wenn show ist verantwortlich für die Sitze, dann wäre es besser, wenn es vollständig verantwortlich ist. Im Moment ist es nicht komplett verantwortlich, weil Sitze reserviert werden können, ohne dass die Show weiß. Diese Fragmentierung der Verantwortlichkeiten ist seltsam.

können Sie show voll verantwortlich setzen von nicht Seat zum Reservation aussetzt, durch den Sitzstatus Manipulationen hinter Hilfsmethoden versteckt:

private boolean reserveSeat(int selectedRow, int selectedSeat) { 
    if (show.isSeatReserved(selectedRow, selectedSeat)) { 
     return false; 
    } else { 
     show.reserveSeat(selectedRow, selectedSeat); 
     setRowNumber(selectedRow); 
     setSeatNumber(selectedSeat); 

     return true; 
    } 
} 

Oder, wenn Sie verantwortlich sein, nicht show wollen von den Sitzen, dann sollte es die Sitze überhaupt nicht kennen, so dann würden Sie Plätze nicht durch show, aber eine andere Klasse zugreifen, die verantwortlich dafür ist.

+0

Vielen Dank für diese sehr nützliche Antwort. Wenn Sie die resetSeat-Methode in der show-Klasse verwenden, ist es in Ordnung, dass die show-Klasse ihre Row-Objektmethode aufruft, die wiederum die Seat-Objektmethode aufruft? d. h. dieser Teil .get (selectedRow) .getSeats(). get (selectedSeat) .getReservationStatus() –

+1

Das ist immer noch nicht großartig. Zum Beispiel sollte 'Row'' 'getSeats' 'nicht so darstellen, sondern' getSeat (int) 'accessor (ersetzt' getSeats(). Get (selectedSeat) '.) Sie möchten die langen verketteten Aufrufe so weit wie möglich reduzieren, wie erklärt auf https://en.wikipedia.org/wiki/Law_of_Demeter – janos

+0

danke @janos, so um Ihr Beispiel zu unterstützen, habe ich jetzt in der Showklasse \t 'public boolean isSeatReserved (int selectedRow, int selectedSeat) { \t \t if (getRow (SelectedRow) .getSeat (selectedSeat) .getReservationStatus()) { \t \t \t return true; \t \t} else \t \t \t return false; \t} \t public void reserveSeat (int SelectedRow, int selectedSeat) { \t \t getRow (SelectedRow) .getSeat (selectedSeat).Reservieren(); \t} 'und in Zeile Klasse habe ich 'öffentlichen Sitzplatz getSeat (int selectedSeat) { \t \t Rückkehr sets.get (selectedSeat); \t} 'Ist das was du meinst? Es tut mir leid, dass ich meinen Code im Kommentar nicht formatieren konnte !! –

1

Sie verwenden show als Datenobjekt und setzen die gesamte Logik für die Verarbeitung dieser Daten in der Klasse, die sie enthält. Dies macht eine Datenklasse und die einschließende Klasse eine Gottklasse.

Die Logik für den Umgang mit Daten innerhalb von show wirklich innerhalb der Show Klasse selbst (Daten sind smart) sein sollte.

Sie können eine Methode in der Show Klasse für die Reservierung eines Sitzplatzes machen. Und genauso können Sie eine Methode in der Klasse für die Reservierung eines Sitzplatzes machen.

Dann übergibt man die Nachricht nur an die nächste, bis Sie zu Seat gelangen.


Was ist, wenn Sie die Implementierung von Show geändert, um einen 2D-Array zum Beispiel zu benutzen? Das würde den Code in Ihrer Reservierungsklasse brechen.

Durch diese langen verketteten Aufrufe, und nicht zulassen, dass Klassen ihre eigenen Daten behandeln. Sie machen die Benutzerklassen abhängig von der Implementierung der verwendeten Datenstrukturen.

Wenn Sie eine ändern möchten, müssten Sie alle Benutzerklassen aktualisieren, anstatt nur die eine Klasse, die die Datenstruktur enthält.

+0

Danke dafür, könntest du mir einfach erklären, was du meinst, wenn du sagst, Show ist ein Datenobjekt? –

+0

@UrbanGemz '' 'show''' ist perfekt in der Lage, die Reservierungen selbst zu machen, aber Sie lassen es nicht, Sie verwenden es nur für seine Daten. Das meine ich mit _data object_. –

0

Also danke für die Anregungen, die Rückmeldung hat wirklich geholfen mit meinem Lernen. Also, was ich ging zu tun war, die folgenden, auf der Grundlage der relationsip -> A Reservation (heute Buchung) hat eineanzeigen, A anzeigeneineRow hat, A Rowhat eineSeat (s).

In der Buchungsklasse Ich habe jetzt dieses: Danke @janos

private boolean reserveSeat(int selectedRow, int selectedSeat) { 
    if (show.isSeatReserved(selectedRow, selectedSeat)) { 
     System.out.println("Sorry, that seat has already been booked"); 
     return false; 
    } else { 
     show.reserveSeat(selectedRow, selectedSeat); 
     setRowNumber(selectedRow); 
     setSeatNumber(selectedSeat); 
     System.out.println("This seat has now been booked."); 
     return true; 
    } 
} 

in der Show-Klasse Ich habe diese:

public boolean isSeatReserved(int selectedRow, int selectedSeat) { 
    if (getRow(selectedRow).getSeatStatus(selectedSeat)) { 
     return true; 
    } else 
     return false; 
} 

und in der Zeilenklasse I

public boolean getSeatStatus(int selectedSeat) { 
    return getSeat(selectedSeat).getReservationStatus(); 
} 
haben

Ich dachte, es könnte für andere Leute nützlich sein, die gerade anfangen (wie ich), dies grafisch mit Vorher-Nachher-Diagrammen zu zeigen genommen vom jarchitect Werkzeug, das zeigt, in was für einem Durcheinander mein Code war! Ich benutzte die gleiche Logik, um einige andere Klassen aufzuräumen, die "zu viel wussten".

Before Refactoring

After Refactoring