SlideShare ist ein Scribd-Unternehmen logo
1 von 19
State Design Pattern
GIADA BENFATTO, MANUEL GRAF, MICHAEL KESSLER AKA. V24
Motivation:
 Ermögliche es einem Objekt, sein Verhalten zu
 ändern, wenn sein interner Zustand sich
 ändert
Beispiel
•   Wir modellieren eine Freundin/Freund:
     – Laune: Fröhlich, Neutral, Bockig
     – Wir können mit ihr interagieren: ihr einen Kuss geben, uns mit ihr
       unterhalten, oder sie ärgern
     – Je nach ausgeführte Aktion, ändert sich ihren Zustand (Laune), wie
       unten illustriert:
•   Je nach Zustand wird die Freundin unterschiedlich auf Interaktionen (unterhalten(),
    veraergern(), kussGeben()) reagieren
•    Das äußere Verhalten der Freundin ändert sich also in Abhängigkeit von ihrem inneren
    Zustand.




          Wie löst man das Problem?
Eine Möglichkeit:
•   Aktuelle Zustand durch Integer repräsentieren. NEUTRAL = 0; BOCKIG =1; FRÖHLICH = 2;
•   In jede Operation – kussGeben(), unterhalten(), verärgern() – wird geprüft, welchen Wert
    diese Integer Variable hat, und danach verhandelt, also: if(state == 1){ //Reagiere auf bockige
    weise} elseif(state == 0){ //Reagiere neutral}

     Beispiel:
publicvoid unterhalten() {
if (aktuellerZustand == NEUTRAL) {
System.out.println(„blablabla!”);
else if (aktuellerZustant == BOCKIG) {
System.out.println(“Ich bin sauer, Ich will nichtmitdirreden!”);
       }else if (aktuellerZustant == FRÖHLICH) {
System.out.println(“Hihi, blablabla!”); }
}
Allerdings… Naiver Ansatz
Probleme:
•   Unleserlich/Unübersichtlich
•   Nicht wirklich Objektorientiert
•   Schlechte Wartbarkeitund Erweiterbarkeit=>if/else Konstrukt muss bei jede kleine Änderung
    erweitert werden. Schnell Fehleranfällig.

Und was ist, wenn wir als neue Anforderung möchten, dass bei einen Aufruf von unterhalten()
beim Zustand Neutral, es eine 10% Wahrscheinlichkeit gibt, dass dies in den Zustand Bockig
führt, weil man was falsches gesagt hat?

Reine strukturierte Programmierung also doch keine Gute Idee.

=>Bessere Lösung: Statusobjekte anlegen, die je eine Laune/Zustand
darstellen sollten, und die sich einen Interface teilen.
    – Somit nutzen sie alle die selben Methoden, Implementieren sie jedoch
        unterschiedlich
OO-Entwurfsprinzipe:
•   Identifiziere jene Aspekte, die sich ändern und trenne sie von jenen, die konstant
    bleiben.
       In Zukunft müssen wahrscheinlich neue Zustände integrieren. Die Freundin ändert sich aber nicht.
     Jedoch wird bei dem jetzigen Entwurf bei jede Änderung beeinträchtigt.


•   Offen/Geschlossen–Prinzip (Open/Closed): Entwürfe sollen für Erweiterungen
    offen, aber für Veränderungen geschlossen sein.
       Wie oben: Freundin-Code soll für Veränderungen geschlossen sein, sie soll um neue Zustände
     jederzeit erweitert werden können


•   Kohäsion (= Grad, inwiefern eine Klasse einen einzigen konzentrierten Zweck hat)
    und Delegation: Kapsele Verantwortlichkeiten in eigenen Objekten und delegiere
    Aufrufe an diese Objekte. Es gilt: eine Klasse, eine Verantwortlichkeit.
        Hier ist es Deutlich: Zustände müssen in eigenen Objekten gekapselt werden
Neuer Freundin Code, nach diesen
Prinzipien erstellt:
Implementierung:
• Interface IZustand(){
      Public void unterhalten();
      Public voidveraergern();
      Public voidkussGeben();
  }

  Class Neutral implementsIZustand
  Class Bockig implementsIZustand
  Class FroehlichimplementsIZustand
Die Klasse Freundin:
class Freundin{
publicIZustandaktuellerZustand;
//Setter zum Setzen des Aktuellen Zustands
publicvoidsetAktuellerZustand(IZustandpAktuellerZustand){
aktuellerZustand= pAktuellerZustand;
       }
public Freundin(){
setAktuellerZustand(newNeutral(this));
       }

publicvoidunterhalten(){
aktuellerZustand.unterhalten();
      }
publicvoidkussGeben(){
aktuellerZustand.kussGeben();
      }
publicvoidveraergern(){
aktuellerZustand.veraergern();
      }
}
Der neutrale Zustand
class Neutral implements IZustand{
//Konstruktur. MitFreundinparametrisiert
public Neutral (FreundinpFreundin){
            _freundin = pFreundin;
      }
//Referenz auf die Freundin
private Freundin _freundin;

public void unterhalten(){
System.out.println(“blablabla!“);
      }
public void kussGeben(){
System.out.println(“Hihi, dankeschön!“);
_freundin.setAktuellerZustand(newFröhlich(_freundin));//Zustandsübergang
      }
public void veraergern(){
System.out.println(“Sag mal gehtsnoch?”);
_freundin.setAktuellerZustand(newBockig(_freundin)); //Zustandsübergang
      }
}
Der bockige Zustand
classBockigimplements IZustand{
//Konstruktur. MitFreundinparametrisiert
public neutral (FreundinpFreundin){
            _freundin=pFreundin;
      }
//Referenz auf die Freundin
private Freundin _freundin;

public void unterhalten(){
System.out.println(“Ich bin sauer, Ich will nichtmit dir reden!“);
      }
public void kussGeben(){
System.out.println(“Na gut! IchHabdichwiederlieb…“);
      _freundin.setAktuellerZustand(new Neutral(_freundin)); // Zustandsübergang
      }
public void veraergern(){
System.out.println(“Du machstallesbloßnochschlimmer!”);
}
}
Der fröhliche Zustand
class Froehlich implements IZustand{
//Konstruktur. MitFreundinparametrisiert
public neutral (FreundinpFreundin){
            _freundin=pFreundin;
       }
//Referenz auf die Freundin
private Freundin _freundin;

public void unterhalten(){
System.out.println(“Hihi, blablabla!“);
      }
public void kussGeben(){
System.out.println(“Oh la la…“);
            _freundin.setAktuellerZustand(newFroehlich(_freundin)); //Zustandsübergang
      }
public void veraergern(){
System.out.println(“Hey! Dabei war ich so gut drauf!”);
_freundin.setAktuellerZustand(newNeutral(_freundin));
      }
}
Testrun:
Freundin freundin=new Freundin();
//Defaultzustand: Neutral -_-
freundin.unterhalten(); // blablabla!
freundin.veraergern(); // Sag mal gehtsnoch?

// => Ab jetzt: Bockig 
freundin.unterhalten(); // Ich bin sauer, Ich will nichtmit dir reden!
Freundin.kussGeben(); // Na gut!IchHabdichwiederlieb

// => Ab jetzt. Neutral -_-
freundin.kussGeben(); // Hihi. :-)

// => Ab jetzt: Fröhlich 
freundin.unterhalten(); // Hihi,blablabla!
Freundin.kussGeben(); // Oh la la…
Variationen

        Definition der Zustandsübergänge


           Zustände bestimmen Folgezustand


           Kontext bestimmt Folgezustände


        Folgezustand als Rückgabewert von operate()
Lebenszeit von Zustandsobjekten:
 Erzeugung bei Bedarf                    Erzeugung im Voraus
 Bei seltener Änderung der Zustände      Bei häufigen Zustandswechseln
 Referenz vom Context auf                Einmalige Kosten zur Instanziierung der
 Zustandsobjekte nicht notwendig.        Zustandsobjekte
                                         Kein Kosten für das Zerstören von
                                         Zustandsobjekten
                                         Allerdings muss das Kontextobjekt zu
                                         jedem möglichen Zustandsobjekt eine
                                         Referenz halten.


Gemeinsame Nutzung von Zustandsobjekten:

Wenn die Zustände keinen internen Zustand haben, so können zur Einsparung von
Ressourcen verschiedene Kontextobjekte die selben Zustandsobjekte nutzen
Anwendungsfälle

• Ein Objekt soll sein äußeres Verhalten zur Laufzeit in Abhängigkeit von
  seinem Zustand ändern.



• Ein Objekt besitzt eine Reihe von Methoden ähnlicher Struktur, die sich
  aus immer gleichen Bedingungsanweisungen zusammensetzen.
Vorteile                         Nachteile
• Intuitiv und Verständlich      • Mehr Klassen
• Hohe Kohäsion/klare            • Weniger Kompakt
  Trennung der
  Verantwortlichkeiten
• Änderungsstabil
• Erweiterbar ohne den Kontext
  zu ändern
• Wiederverwendbarkeit
• Weniger fehlerträchtig
Quellen
• http://www.philipphauer.de/study/se/design-pattern/state.php

• Head First Design Pattern - Kapitel 10: The State of Things

Weitere ähnliche Inhalte

Andere mochten auch

Andere mochten auch (11)

Nuevos horizontes
Nuevos horizontesNuevos horizontes
Nuevos horizontes
 
DIE MARKTMEINUNG AUS STUTTGART
DIE MARKTMEINUNG AUS STUTTGARTDIE MARKTMEINUNG AUS STUTTGART
DIE MARKTMEINUNG AUS STUTTGART
 
La gestión de los sistemas educativos
La gestión de los sistemas educativosLa gestión de los sistemas educativos
La gestión de los sistemas educativos
 
Mapaconceptual primaria 110911182946-phpapp01
Mapaconceptual primaria  110911182946-phpapp01Mapaconceptual primaria  110911182946-phpapp01
Mapaconceptual primaria 110911182946-phpapp01
 
Xaile1
Xaile1Xaile1
Xaile1
 
Revista nº 5 edsa original
Revista nº 5 edsa originalRevista nº 5 edsa original
Revista nº 5 edsa original
 
TASK 7
TASK 7 TASK 7
TASK 7
 
Mapa conceptual de blue
Mapa conceptual de blueMapa conceptual de blue
Mapa conceptual de blue
 
guidesassidimatera
guidesassidimateraguidesassidimatera
guidesassidimatera
 
Calendário
CalendárioCalendário
Calendário
 
Livros laura rodrigues
Livros laura rodriguesLivros laura rodrigues
Livros laura rodrigues
 

LMU V24 – State Design Pattern

  • 1. State Design Pattern GIADA BENFATTO, MANUEL GRAF, MICHAEL KESSLER AKA. V24
  • 2. Motivation: Ermögliche es einem Objekt, sein Verhalten zu ändern, wenn sein interner Zustand sich ändert
  • 3. Beispiel • Wir modellieren eine Freundin/Freund: – Laune: Fröhlich, Neutral, Bockig – Wir können mit ihr interagieren: ihr einen Kuss geben, uns mit ihr unterhalten, oder sie ärgern – Je nach ausgeführte Aktion, ändert sich ihren Zustand (Laune), wie unten illustriert:
  • 4. Je nach Zustand wird die Freundin unterschiedlich auf Interaktionen (unterhalten(), veraergern(), kussGeben()) reagieren • Das äußere Verhalten der Freundin ändert sich also in Abhängigkeit von ihrem inneren Zustand. Wie löst man das Problem?
  • 5. Eine Möglichkeit: • Aktuelle Zustand durch Integer repräsentieren. NEUTRAL = 0; BOCKIG =1; FRÖHLICH = 2; • In jede Operation – kussGeben(), unterhalten(), verärgern() – wird geprüft, welchen Wert diese Integer Variable hat, und danach verhandelt, also: if(state == 1){ //Reagiere auf bockige weise} elseif(state == 0){ //Reagiere neutral} Beispiel: publicvoid unterhalten() { if (aktuellerZustand == NEUTRAL) { System.out.println(„blablabla!”); else if (aktuellerZustant == BOCKIG) { System.out.println(“Ich bin sauer, Ich will nichtmitdirreden!”); }else if (aktuellerZustant == FRÖHLICH) { System.out.println(“Hihi, blablabla!”); } }
  • 6. Allerdings… Naiver Ansatz Probleme: • Unleserlich/Unübersichtlich • Nicht wirklich Objektorientiert • Schlechte Wartbarkeitund Erweiterbarkeit=>if/else Konstrukt muss bei jede kleine Änderung erweitert werden. Schnell Fehleranfällig. Und was ist, wenn wir als neue Anforderung möchten, dass bei einen Aufruf von unterhalten() beim Zustand Neutral, es eine 10% Wahrscheinlichkeit gibt, dass dies in den Zustand Bockig führt, weil man was falsches gesagt hat? Reine strukturierte Programmierung also doch keine Gute Idee. =>Bessere Lösung: Statusobjekte anlegen, die je eine Laune/Zustand darstellen sollten, und die sich einen Interface teilen. – Somit nutzen sie alle die selben Methoden, Implementieren sie jedoch unterschiedlich
  • 7. OO-Entwurfsprinzipe: • Identifiziere jene Aspekte, die sich ändern und trenne sie von jenen, die konstant bleiben. In Zukunft müssen wahrscheinlich neue Zustände integrieren. Die Freundin ändert sich aber nicht. Jedoch wird bei dem jetzigen Entwurf bei jede Änderung beeinträchtigt. • Offen/Geschlossen–Prinzip (Open/Closed): Entwürfe sollen für Erweiterungen offen, aber für Veränderungen geschlossen sein. Wie oben: Freundin-Code soll für Veränderungen geschlossen sein, sie soll um neue Zustände jederzeit erweitert werden können • Kohäsion (= Grad, inwiefern eine Klasse einen einzigen konzentrierten Zweck hat) und Delegation: Kapsele Verantwortlichkeiten in eigenen Objekten und delegiere Aufrufe an diese Objekte. Es gilt: eine Klasse, eine Verantwortlichkeit. Hier ist es Deutlich: Zustände müssen in eigenen Objekten gekapselt werden
  • 8. Neuer Freundin Code, nach diesen Prinzipien erstellt:
  • 9. Implementierung: • Interface IZustand(){ Public void unterhalten(); Public voidveraergern(); Public voidkussGeben(); } Class Neutral implementsIZustand Class Bockig implementsIZustand Class FroehlichimplementsIZustand
  • 10. Die Klasse Freundin: class Freundin{ publicIZustandaktuellerZustand; //Setter zum Setzen des Aktuellen Zustands publicvoidsetAktuellerZustand(IZustandpAktuellerZustand){ aktuellerZustand= pAktuellerZustand; } public Freundin(){ setAktuellerZustand(newNeutral(this)); } publicvoidunterhalten(){ aktuellerZustand.unterhalten(); } publicvoidkussGeben(){ aktuellerZustand.kussGeben(); } publicvoidveraergern(){ aktuellerZustand.veraergern(); } }
  • 11. Der neutrale Zustand class Neutral implements IZustand{ //Konstruktur. MitFreundinparametrisiert public Neutral (FreundinpFreundin){ _freundin = pFreundin; } //Referenz auf die Freundin private Freundin _freundin; public void unterhalten(){ System.out.println(“blablabla!“); } public void kussGeben(){ System.out.println(“Hihi, dankeschön!“); _freundin.setAktuellerZustand(newFröhlich(_freundin));//Zustandsübergang } public void veraergern(){ System.out.println(“Sag mal gehtsnoch?”); _freundin.setAktuellerZustand(newBockig(_freundin)); //Zustandsübergang } }
  • 12. Der bockige Zustand classBockigimplements IZustand{ //Konstruktur. MitFreundinparametrisiert public neutral (FreundinpFreundin){ _freundin=pFreundin; } //Referenz auf die Freundin private Freundin _freundin; public void unterhalten(){ System.out.println(“Ich bin sauer, Ich will nichtmit dir reden!“); } public void kussGeben(){ System.out.println(“Na gut! IchHabdichwiederlieb…“); _freundin.setAktuellerZustand(new Neutral(_freundin)); // Zustandsübergang } public void veraergern(){ System.out.println(“Du machstallesbloßnochschlimmer!”); } }
  • 13. Der fröhliche Zustand class Froehlich implements IZustand{ //Konstruktur. MitFreundinparametrisiert public neutral (FreundinpFreundin){ _freundin=pFreundin; } //Referenz auf die Freundin private Freundin _freundin; public void unterhalten(){ System.out.println(“Hihi, blablabla!“); } public void kussGeben(){ System.out.println(“Oh la la…“); _freundin.setAktuellerZustand(newFroehlich(_freundin)); //Zustandsübergang } public void veraergern(){ System.out.println(“Hey! Dabei war ich so gut drauf!”); _freundin.setAktuellerZustand(newNeutral(_freundin)); } }
  • 14. Testrun: Freundin freundin=new Freundin(); //Defaultzustand: Neutral -_- freundin.unterhalten(); // blablabla! freundin.veraergern(); // Sag mal gehtsnoch? // => Ab jetzt: Bockig  freundin.unterhalten(); // Ich bin sauer, Ich will nichtmit dir reden! Freundin.kussGeben(); // Na gut!IchHabdichwiederlieb // => Ab jetzt. Neutral -_- freundin.kussGeben(); // Hihi. :-) // => Ab jetzt: Fröhlich  freundin.unterhalten(); // Hihi,blablabla! Freundin.kussGeben(); // Oh la la…
  • 15. Variationen Definition der Zustandsübergänge Zustände bestimmen Folgezustand Kontext bestimmt Folgezustände Folgezustand als Rückgabewert von operate()
  • 16. Lebenszeit von Zustandsobjekten: Erzeugung bei Bedarf Erzeugung im Voraus Bei seltener Änderung der Zustände Bei häufigen Zustandswechseln Referenz vom Context auf Einmalige Kosten zur Instanziierung der Zustandsobjekte nicht notwendig. Zustandsobjekte Kein Kosten für das Zerstören von Zustandsobjekten Allerdings muss das Kontextobjekt zu jedem möglichen Zustandsobjekt eine Referenz halten. Gemeinsame Nutzung von Zustandsobjekten: Wenn die Zustände keinen internen Zustand haben, so können zur Einsparung von Ressourcen verschiedene Kontextobjekte die selben Zustandsobjekte nutzen
  • 17. Anwendungsfälle • Ein Objekt soll sein äußeres Verhalten zur Laufzeit in Abhängigkeit von seinem Zustand ändern. • Ein Objekt besitzt eine Reihe von Methoden ähnlicher Struktur, die sich aus immer gleichen Bedingungsanweisungen zusammensetzen.
  • 18. Vorteile Nachteile • Intuitiv und Verständlich • Mehr Klassen • Hohe Kohäsion/klare • Weniger Kompakt Trennung der Verantwortlichkeiten • Änderungsstabil • Erweiterbar ohne den Kontext zu ändern • Wiederverwendbarkeit • Weniger fehlerträchtig
  • 19. Quellen • http://www.philipphauer.de/study/se/design-pattern/state.php • Head First Design Pattern - Kapitel 10: The State of Things