State

Przeznaczenie

  • Umożliwia obiektowi zmianę zachowania, gdy zmienia się jego stan wewnętrzny. Dzięki temu obiekt zdaje się zmieniać wówczas swoją klasę.

Kontekst

  • Zachowanie obiektu zależy od jego stanu, a obiekt ten musi zmieniać swoje zachowanie w czasie wykonywania programu w zależności od stanu

  • Operacje zawierają duże, wieloczęściowe instrukcje warunkowe, które zależą od stanu obiektu - wzorzec State przenosi każde rozgałęzienie warunkowe do oddzielnej klasy

Problem

  • Chcemy umożliwić obiektowi zmianę zachowania w momencie zmiany wewnętrznego stanu obiektu hermetyzując stan w postaci klasy

Struktura

_images/State.png

Uczestnicy

Context

  • definiuje interfejs dla klientów

  • utrzymuje egzemplarz podklasy ConcreteState, definiujący bieżący stan

State – definiuje interfejs enkapsulujący zachowanie związane z danym stanem obiektu Context

ConcreteState – każda podklasa implementuje zachowanie związane ze stanem kontekstu

Współpraca

Kontekst (Context) deleguje żądania specyficzne dla stanu do bieżącego obiektu ConcreteState. Kontekst może przekazywać samego siebie jako argument do obiektu State obsługującego żądanie. Umożliwia to obiektowi stanu dostęp do kontekstu, gdy jest to konieczne.

Kontekst jest podstawowym interfejsem dla klientów:

  • klienci mogą konfigurować kontekst za pomocą obiektów State

  • z chwilą skonfigurowania kontekstu klienci nie muszą bezpośrednio zajmować się obiektami stan

O tym, który stan następuje po innym i w jakich okolicznościach, może decydować albo kontekst, albo podklasy ConcreteState.

Konsekwencje

  1. Umiejscowienie zachowania specyficznego dla stanu i rozdzielenie zachowania w wypadku różnych stanów. Kod dla każdego stanu znajduje się w osobnej klasie. Ułatwia to dodawanie nowych stanów (nie wymaga daleko idących modyfikacji istniejącego kodu). Eliminuje konieczność dzielenia kodu metod na bloki właściwe dla stanów (bloki switch).

  2. Jawność przejść między stanami. Z perspektywy klientów (Context) przejścia między stanami są atomowe. Dochodzi do nich poprzez zmianę wartości jednej zmiennej.

  3. Możliwość współdzielenia obiektów typu State. Jeśli obiekty typu State nie mają swoich zmiennych egzemplarzowych, to konteksty mogą je współdzielić.

Implementacja

  • Który z uczestników definiuje przejścia między stanami?

  • Tworzenie i niszczenie obiektów typu State

Wzorce pokrewne

  1. Flyweight – stosowany gdy można współdzielić obiekty reprezentujące stan

  2. Singleton – obiekty stanu są często implementowane jako singletony

Podsumowanie

  1. Wzorzec projektowy State opisuje sytuację, w której zachowanie obiektu jest determinowane przez wewnętrzny stan, który może się zmieniać w reakcji na zachodzące zdarzenia.

  2. Zapewnia lepszą skalowalność logiki zawiązanej z zarządzaniem stanów obiektu.

  3. Poprzez hermetyzację stanów w klasach lokalizujemy przyszłe zmiany w kodzie.

State a Strategy – porównanie

Wzorce State i Strategy mają ten sam diagram klas, różni się cel ich stosowania:

  • gdy stosowany jest wzorzec Strategy, obiekty Context są konfigurowane przy użyciu zachowania lub algorytmu

  • gdy stosowany jest wzorzec State, obiekt Context zmienia swoje zachowanie odpowiednio do zmian swojego stanu