2016-10-29 3 views
5

I-EntwurfsmusterStaat Muster java

in Java lerne ich tat durch einige links.I durch staatliche Muster eine Waschmaschine zu entwerfen versuche

Ich habe eine Abfrage in Bezug auf die Umsetzung der staatlichen Design

Muster
public interface State { 

    public void openLid(); 
    public void closeLid(); 
    public void start(); 
    public void stop(); 
    public void washing(); 
    } 

public class Idle implements State{ 
//implementing overidden methods 
....... 

} 

public class Washing implements State { 
     //implementing overidden methods 
     ....... 
    } 


public class WashingMachine { 
    State state; 

    public WashingMachine(State state) { 
    this.state = new Idle(); 
    } 

    public State getState() { 
    return state; 
    } 

    public void setState(State state) { 
    this.state = state; 
    } 

} 

ich möchte wissen, wenn es zwischen Zustand zwischen Leerlauf Waschen der Implementierung Umschalten kann auf zwei Arten sein, die Säge über net

ist

1. WaschMaschine Klasse implementiert Staat Schnittstelle und Schaltzustand von Idle zu Wasch oder umgekehrt, basierend auf einer Bedingung

2. Idle und Washing Klasse WaschMaschine als Mitglied hat Variable.

Bitte jemand kann vorschlagen, ich bin ein wenig verwirrt über die Implementierung Teil.

+1

Weder Ihre Ideen wären eigentlich in Ordnung sein –

Antwort

3

Bevor ich Ihre Frage anspreche, ziehe ich es vor, die Idee des Musters zu überprüfen und Ihnen einige kleine Änderungen in Ihrem Code vorzuschlagen.

Mit dem Statusmuster kann ein Objekt sein Verhalten ändern, wenn sich der interne Status ändert.

In Ihrem Fall sind Leerlauf und Waschen gute Kandidaten, da Zustände und WashingMachine ein guter Kandidat sind, um das Zustandsobjekt zu tragen.

jedoch drei Bemerkungen:

1) durch die Zustände bereitgestellten Verfahren sollten einige Maßnahmen sein, die Umsetzungen nach unterscheiden, unter denen das Objekt angeben.

In Ihrer Erklärung:

public interface WashingMachineState {  
    public void openLid(); 
    public void closeLid(); 
    public void start(); 
    public void stop(); 
    public void washing(); 
    } 

washing() ist keine Aktion, sondern ein Zustand.
Es ist die start() Aktion, die den Status von Leerlauf zu Waschen ändert.

In dem Zustand, Muster, das Objekt mit einem Zustand wird den Kontext genannt. In Ihrem Fall ist der Kontext WashingMachine.

2) In dem Zustandsmuster ist die Idee, dass der Kontext einige Aktionen ausführen möchte, deren Verhalten sich entsprechend dem aktuellen Status ändert.
Um dies zu erreichen, delegiert der Kontext seine Verarbeitungen an seine aktuelle Statusinstanz.
Es vermeidet viele wenn mit - sonst wenn im Rahmen (für jede Verarbeitung), und es erlaubt auch die Komplexität des Kontextes zu reduzieren, denn wenn man den Zustand Muster verwenden zu können, Familien von Verhaltensweisen erhalten:

  • Verhalten, wenn wir im Ruhezustand sind in der IdleState Klasse befinden.

  • Verhalten, wenn wir im Waschzustand sind in WashingState Klasse.

  • und so für ...

die Aktionen ausführen zu können, müssen Staat Instanzen den Kontext (WashingMachine).
Um diese Frage zu adressieren, haben Sie zwei Möglichkeiten tun:

Entweder das WashingMachine Objekt als ein Feld in der Zustand Instanz oder Weitergabe dieses als Argument, wenn der Kontext WashingMachine Objekt delegiert die Verarbeitung in den Zustand zu speichern.

Ich schlage vor, Sie den zustandslosen Weg zu verwenden.
So, wenn die startWashing()-Operation auf eine WashingMachine Instanz aufgerufen wird, sollte die WashingMachine Instanz die Verarbeitung an state.startWashing() delegieren, indem sie sich wie state.startWashing(this) übergeben.
Der Staat sollte ein WashingMachine als Parameter angeben:

public interface WashingMachineState {  
    void openLid(WashingMachine machine); 
    void closeLid(WashingMachine machine); 
    void pushStartBtn(WashingMachine machine); 
    void pushStopBtn(WashingMachine machine); 
} 

3) Eigentlich definiert man zwei Zustände: Leerlauf und Waschen.
Diese sollten mit einem stopping Status abgeschlossen werden, da einige Operationen an der Maschine (Öffnen der Tür, Drücken der Start-Btn zum Beispiel ...) ein bestimmtes Verhalten haben, wenn die Maschine im Zustand "ist gestoppt" ist.
Beachten Sie, dass Sie sich mit nur zwei Zuständen fragen können, ob das Muster relevant ist.


Jetzt kann ich auf Ihre Frage beantworten.

Ich möchte wissen, wenn zwischen Zustand zwischen Leerlauf Waschschalt der Umsetzung kann es zwei Möglichkeiten, die Säge über Netz ist

1. WashingMachine Klasse implementiert Staat Schnittstelle und Schaltzustand von Idle Wasch- oder Umgekehrt basierend auf einer Bedingung

2.Idle und Washing-Klasse hat WashingMachine als Elementvariable.

WashingMachine und WashingMachineState s zusammenarbeiten, aber verschiedene Dinge.
Also müssen sie sich nicht auf die gleiche Schnittstelle verlassen.
Hinzufügen von WashingMachine Objekt als Felder von Zustand Unterklassen ist eine Möglichkeit.
Wie erläutert, können Sie auch den WashingMachine als Parameter der State-Methoden übergeben.

Beachten Sie, dass es nicht direkt die WashingMachine, die den Wechsel von einem Zustand zu einem anderen durchführt.
Dies wird vom Staat durchgeführt.
Und Staaten sollten WashingMachine.changeState() aufrufen, um es durchzuführen.

Die WashingMachine könnte sein:

public class WashingMachine { 

    private WashingMachineState state; 

    public WashingMachine() { 
    this.state = new Idle(); 
    }   

    protected void changeState(WashingMachineState state) { 
    this.state = state;  
    } 

    public void openLid(){ 
    state.openLid(this); 
    } 

    public void closeLid(){ 
    state.closeLid(this);   
    } 
    public void pushStartBtn(){ 
    state.pushStartBtn(this); 
    } 

    public void pushStopBtn(){ 
    state.pushStopBtn(this); 
    } 

    public State getState() { 
     return state; 
    } 

} 

Erläuterungen zu Veränderungen an WashingMachine:

  • changeStatesetState als aussagekräftiger ist, als Zustandsmuster verwendet wird.

  • changeState(State) könnte den protected Modifikator verwenden, um die Sichtbarkeit dieser Methode zu verringern und natürlich Zustand Subklassen sollte als WashingMachine im gleichen Paket sein. Es ist ein Implementierungsdetail, das in Java aktiviert ist. Bei anderen OOP-Sprachen haben Sie natürlich andere Alternativen.

über vom Leerlauf zu waschen Schalt, glaube ich, dass es im IdleState Zustand nur möglich sein soll, als pushStartBtn() aufgerufen wird. Hier

ist ein Beispiel:

public class IdleState implements State {  
    public void openLid(WashingMachine machine){ 
     ... 
    } 
    public void closeLid(WashingMachine machine){ 
     ... 
    } 
    public void pushStartBtn(WashingMachine machine){ 
     //do processing with machine to begin effectively the washing 
     ... 
     machine.changeState(new WashingState()); 
    } 

    public void pushStopBtn(WashingMachine machine){ 
     ... 
    } 
} 
+0

@ coder25 Ich habe den dritten Punkt geändert. Ein Haltezustand scheint relevanter zu sein als ein geöffneter Türzustand. Der Zustand der geöffneten Tür ist kein Zustand der ersten Stufe, das wäre eher ein Unterzustand. Nicht viel Interesse, es zu vertreten. – davidxxx

+0

Zum Ändern des Status ('machine.changeState (new WashingState())') - Ist es akzeptabel, alle Zustände in der Kontextklasse mit Getter zu haben und jeden Zustand wie 'machine.changeState (machine.getWashingState()) auszuführen 'um die Staatsobjekte Singleton zu halten? – user7

+0

@ user7 Wenn die Zustandsobjekte zustandslos sind (zusammenzufassen: keine Instanzfelder in den Zustandsklassen), ist dies möglich und sogar eine gute Idee. In diesem Fall würde ich anstelle von Gettern wahrscheinlich enums zur Darstellung von Zuständen verwenden: "public enum WashingMachineState {WASHING, IDLE, STOPPING}", da es Singletons aus der Box bereitstellt, während es ein geradliniger Weg ist. – davidxxx

0

Okay, wir gehen durch Ihre beiden Ideen:

1.) Ist die Waschmaschine ein Zustand? Nein, definitiv nicht. Warum sollte dann die Zustandsschnittstelle implementiert werden?

2.) Das funktioniert fast, aber es macht die Zustände nicht wiederverwendbar (was für eine kleine Implementierung wie diese nicht schlecht ist, aber für so etwas wie ein Spiel, es ist schrecklich). Sie können nur die Zustände einer Waschmaschine sein. Was, wenn ich diese Zustände für eine Spülmaschine benutzen möchte?

Was sollten Sie tun:

Machen Sie eine Schnittstelle oder Klasse, so etwas wie State, und machen die WaschMaschine dies umzusetzen, dann stattdessen eine konkrete Klasse zu verwenden, erstellen Sie ein Feld State in den Staaten.

Beispiel:

public abstract class StateManager { 
    public State state; 

    public void setState(State newState) { 
     state = newState; 
     newState.parent = this; 
    } 
    public State getState() { 
     return state; 
    } 
} 

Zustand:

public abstract class State { 
    public StateManager parent; 
    // Whenever you want to set the object's state, use this 
} 

Beispiel Zustand:

public class WashingState extends State { 
    // your methods here 
} 

Beispiel Zustandsmanager:

public class WashingMachine extends StateManager { 
    // your methods here. 
} 

Ich habe an Stelle der Benutzeroberfläche alles geändert, weil sie das Erstellen einiger Objekte erleichtern (wie wenn man eine Spülmaschine und eine Waschmaschine machen möchte, dann kann man die Waschteile daraus extrahieren und eine separate Klasse dafür erstellen)

+0

können Sie mit Beispiel erklären – coder25

+0

ich etwas posten, wenn ich nach Hause komme –

+0

können Sie bitte etwas für Ihr Design Empfehlung schreiben – coder25

1

ich denke, dass eine bessere Wahl

public enum State{IDLE,WASHING}; 

und verwenden, die zu schaffen wäre.Diese enum könnte sogar WashingMachineState genannt werden, da die Staaten, die Sie erwähnt haben, nur Waschmaschine angegeben werden - sie werden nicht wiederverwendbar sein, so dass kein Punkt der Schnittstellen hier.

Wenn Sie die gleichen Zustände zwischen verschiedenen Geräten teilen möchten, z. WashingMachine und DishWasher dann könnte man

public interface Statefull{ 
    public State getState(); 
    public void changeState(State newState); 
} 

Und lassen WashingMachine und DishWasher implementieren Statefull Schnittstelle verwenden. Mit der Standardschnittstellen-Implementierung von Java 8 können Sie sogar die Getter-Implementierung in die Schnittstelle einfügen, so dass in implementierenden Klassen kein Standardcode enthalten ist.

+0

http://www.superglobals.net/java-state-design-pattern/ Ich lese durch diesen Link.Es definiert das Zustandsmuster – coder25

+0

Ich erweitere es nicht für die Spülmaschine.Ich möchte lernen, wie man es benutzt Zustandsmuster – coder25