Jakie są różnice między wzorcem projektowania strategii a wzorcem projektowania państwa? Przeglądałem sporo artykułów w Internecie, ale nie mogłem wyraźnie zrozumieć różnicy.
Czy ktoś może wyjaśnić różnicę w terminach laika?
design-patterns
strategy-pattern
state-pattern
Chin Tser
źródło
źródło
Odpowiedzi:
Szczerze mówiąc, te dwa wzorce są dość podobne w praktyce, a różnica między nimi różni się w zależności od tego, kogo zapytasz. Niektóre popularne wybory to:
„Klasyczna” implementacja pasowałaby do stanu lub strategii dla każdego elementu na liście, ale można spotkać hybrydy, które mają mieszankę obu. To, czy dany jest bardziej stanem-y czy strategią-y, jest ostatecznie pytaniem subiektywnym.
źródło
getStatus()
metodę, która zwróci różne statusy w zależności od stanu obiektu, ale obiekt wywołujący tę metodę nie musi być kodowany inaczej, aby uwzględnić każdy potencjalny stan.źródło
Różnica polega po prostu na tym, że rozwiązują różne problemy:
Konstrukcje do osiągnięcia tych różnych celów są jednak bardzo podobne; oba wzorce są przykładami kompozycji z delegowaniem.
Kilka uwag na temat ich zalet:
Korzystając z State wzór The (kontekst) Klasa państwowe gospodarstwa jest zwolniony na podstawie wiedzy o jakim państwie lub wpisz to jest i co stwierdza lub typy, które są dostępne. Oznacza to, że klasa jest zgodna z zasadą projektowania otwartego-zamkniętego (OCP): klasa jest zamknięta ze względu na zmiany stanów / typów, ale stany / typy są otwarte na rozszerzenia.
Dzięki zastosowaniu wzorca strategii klasa wykorzystująca algorytm (kontekst) jest odrywana od wiedzy o tym, jak wykonać określone zadanie (- „algorytm”). Ta sprawa powoduje również przestrzeganie OCP; klasa jest zamknięta dla zmian dotyczących sposobu wykonania tego zadania, ale projekt jest bardzo otwarty na dodatki innych algorytmów do rozwiązania tego zadania.
Prawdopodobnie poprawia to również przestrzeganie przez klasę kontekstu zasady pojedynczej odpowiedzialności (SRP). Ponadto algorytm staje się łatwo dostępny do ponownego wykorzystania przez inne klasy.
źródło
Wzory projektowe nie są tak naprawdę „świeckimi” koncepcjami, ale postaram się, aby było to jak najbardziej jasne. Dowolny wzór projektowy można rozważyć w trzech wymiarach:
Porównajmy stan i strategię.
Problem rozwiązuje wzór
Stan jest używany w jednym z dwóch przypadków [książka GoF str. 306] :
Jeśli chcesz się upewnić, że rzeczywiście masz problem rozwiązany przez wzorzec stanu, powinieneś być w stanie modelować stany obiektu za pomocą skończonej maszyny stanów . Zastosowany przykład można znaleźć tutaj .
Każde przejście stanu jest metodą w interfejsie stanu. Oznacza to, że w przypadku projektu musisz być całkowicie pewien zmian stanu przed zastosowaniem tego wzorca. W przeciwnym razie dodanie lub usunięcie przejść będzie wymagało zmiany interfejsu i wszystkich klas, które go implementują.
Osobiście nie uznałem tego wzoru za przydatny. Zawsze możesz zaimplementować maszyny stanów skończonych za pomocą tabeli odnośników (nie jest to metoda OO, ale działa całkiem dobrze).
Strategia jest stosowana do następujących [książka GoF str. 316] :
Ostatni przypadek zastosowania Strategii dotyczy refaktoryzacji znanej jako Zamień warunkowe na polimorfizm .
Podsumowanie: Stan i strategia rozwiązują bardzo różne problemy. Jeśli problemu nie można modelować za pomocą skończonej maszyny stanów, prawdopodobnie wzorzec stanu jest nieodpowiedni. Jeśli twój problem nie dotyczy enkapsulacji wariantów złożonego algorytmu, strategia nie ma zastosowania.
Struktura statyczna wzoru
Stan ma następującą strukturę klas UML:
Strategia ma następującą strukturę klas UML:
Podsumowanie: pod względem struktury statycznej te dwa wzory są w większości identyczne. W rzeczywistości narzędzia wykrywające wzorce, takie jak ten, uważają, że „ struktura wzorców [...] jest identyczna, co zabrania ich rozróżniania w procesie automatycznym (np. Bez odwoływania się do informacji pojęciowych) ”.
Może jednak wystąpić zasadnicza różnica, jeśli ConcreteStates samodzielnie zdecyduje o przejściu stanu (patrz powiązania „ może określić ” na powyższym diagramie). Powoduje to sprzężenie między konkretnymi stanami. Na przykład (patrz następna sekcja) stan A określa przejście do stanu B. Jeśli klasa Context decyduje o przejściu do następnego konkretnego stanu, zależności te znikają.
Dynamika wzoru
Jak wspomniano w sekcji Problem powyżej, stan oznacza, że zachowanie zmienia się w czasie wykonywania w zależności od stanu obiektu. Dlatego stosuje się pojęcie przejścia stanu , jak omówiono w związku ze skończoną maszyną stanu . [GoF] wspomina, że przejścia można zdefiniować w podklasach ConcreteState lub w scentralizowanej lokalizacji (takiej jak lokalizacja oparta na tabeli).
Załóżmy prosty automat skończony:
Zakładając, że podklasy decydują o zmianie stanu (zwracając następny obiekt stanu), dynamika wygląda mniej więcej tak:
Aby pokazać dynamikę strategii , warto pożyczyć prawdziwy przykład .
Podsumowanie : Każdy wzorzec używa wywołania polimorficznego, aby zrobić coś w zależności od kontekstu. We wzorcu stanu wywołanie polimorficzne (przejście) często powoduje zmianę w następnym stanie . We wzorcu strategii połączenie polimorficzne zazwyczaj nie zmienia kontekstu (np. Płatność kartą kredytową nie oznacza, że następnym razem zapłacisz przez PayPal). Ponownie, dynamika wzorca stanu jest określona przez odpowiadającą mu maszynę stanu skończonego, która (dla mnie) jest niezbędna do poprawnego zastosowania tego wzorca.
źródło
Wzorzec strategii obejmuje przeniesienie implementacji algorytmu z klasy hostującej i umieszczenie go w osobnej klasie. Oznacza to, że klasa hosta nie musi zapewniać implementacji każdego algorytmu, co może prowadzić do nieczytelnego kodu.
Algorytmy sortowania są zwykle używane jako przykład, ponieważ wszystkie robią to samo (sortowanie). Jeśli każdy inny algorytm sortujący zostanie umieszczony w swojej własnej klasie, klient może łatwo wybrać algorytm, który ma być używany, a wzorzec zapewnia łatwy dostęp do niego.
Wzorzec stanu obejmuje zmianę zachowania obiektu, gdy zmienia się stan obiektu. Oznacza to, że klasa hosta nie zapewnia implementacji zachowania dla wszystkich różnych stanów, w których może się znajdować. Klasa hosta zwykle zawiera w sobie klasę zapewniającą funkcjonalność wymaganą w danym stanie i przełącza się na inną klasę kiedy zmienia się stan.
źródło
Rozważ system IVR (Interactive Voice Response) obsługujący połączenia z klientami. Możesz zaprogramować go do obsługi klientów na:
Aby poradzić sobie z tą sytuacją, możesz użyć Wzorca Stanu .
Ten proces łączenia klienta z szefem wsparcia można sam zaimplementować za pomocą wzorca strategii, w którym kierownictwo jest wybierane na podstawie:
Wzorzec strategii decyduje o tym, „ jak ” wykonać pewne działanie, a wzorzec stanu decyduje o tym, „ kiedy ” je wykonać.
źródło
Strategia reprezentuje obiekty, które „coś robią”, z takimi samymi wynikami początkowymi i końcowymi, ale wewnętrznie przy użyciu różnych metod. W tym sensie są one analogiczne do przedstawiania wykonania czasownika. Wzorzec stanu OTOH używa obiektów, które „są” czymś - stanem operacji. Chociaż mogą również reprezentować operacje na tych danych, są one bardziej analogiczne do reprezentacji rzeczownika niż czasownika i są dostosowane do maszyn stanu.
źródło
Strategia: strategia jest ustalona i zwykle składa się z kilku kroków. (Sortowanie stanowi tylko jeden krok i dlatego jest bardzo złym przykładem, ponieważ jest zbyt prymitywne, aby zrozumieć cel tego wzorca). Twoja „główna” procedura w strategii wywołuje kilka metod abstrakcyjnych. Na przykład „Enter Room Strategy”, „main-method” to goThroughDoor (), który wygląda następująco: approachDoor (), if (zablokowany ()) openLock (); otwarte drzwi(); enterRoom (); skręcać(); Zamknij drzwi(); if (wasLocked ()) lockDoor ();
Teraz podklasy tego ogólnego „algorytmu” do przemieszczania się z jednego pokoju do drugiego przez możliwe zamknięte drzwi mogą realizować etapy algorytmu.
Innymi słowy, podklasowanie strategii nie zmienia podstawowych algorytmów, a jedynie poszczególne kroki.
TO POWYŻEJ jest wzorcem metody szablonu. Teraz umieść kroki należące do siebie (odblokowanie / zablokowanie i otwarcie / zamknięcie) w ich własnych obiektach implementacyjnych i przekaż im je. Np. Zamek z kluczem i zamek z kartą kodową to dwa rodzaje zamków. Deleguj ze strategii do obiektów „Step”. Teraz masz wzór strategii.
Wzorzec stanu jest czymś zupełnie innym.
Masz obiekt zawijany i obiekt zawinięty. Owinięty to „stan”. Dostęp do obiektu stanu jest możliwy tylko przez jego opakowanie. Teraz możesz zmienić zawinięty obiekt w dowolnym momencie, dlatego opakowanie wydaje się zmieniać swój stan, a nawet „klasę” lub typ.
Np. Masz usługę logowania. Akceptuje nazwę użytkownika i hasło. Ma tylko jedną metodę: logowanie (String userName, String passwdHash). Zamiast samodzielnie decydować, czy logowanie jest akceptowane, czy nie, deleguje decyzję do obiektu stanu. Ten obiekt stanu zwykle po prostu sprawdza, czy kombinacja użytkownik / hasło jest poprawna i wykonuje logowanie. Ale teraz możesz wymienić „Checker” na taki, który pozwala tylko uprzywilejowanym użytkownikom zalogować się (np. W czasie konserwacji) lub na taki, który nie pozwala się zalogować. Oznacza to, że „moduł sprawdzający” wyraża „status logowania” systemu.
Najważniejsza różnica jest taka: kiedy wybierzesz strategię, trzymaj się jej, dopóki z nią nie skończysz. Oznacza to, że nazywasz to „główną metodą” i dopóki ta działa, nigdy nie zmieniasz strategii. OTOH w sytuacji wzorca stanu w czasie wykonywania systemu zmieniasz stan arbitralnie według własnego uznania.
źródło
Wzorzec strategii jest używany, gdy masz wiele algorytmów dla określonego zadania, a klient decyduje o faktycznej implementacji, która ma zostać użyta w czasie wykonywania.
Diagram UML z wiki Artykuł o strategii:
Kluczowe cechy:
Więcej informacji i przykłady ze świata rzeczywistego można znaleźć w tym poście:
Przykład wzorca strategii w świecie rzeczywistym
StanWzorzec pozwala obiektowi zmienić swoje zachowanie, gdy zmienia się jego stan wewnętrzny
Diagram UML z artykułu o stanie Wiki :
Jeśli musimy zmienić zachowanie obiektu w oparciu o jego stan, możemy mieć zmienną stanu w obiekcie i użyć bloku warunków if-else do wykonania różnych akcji w zależności od stanu. Wzorzec stanu służy do zapewnienia systematycznego i luźnego sposobu osiągnięcia tego poprzez kontekst i stan implementacje .
Więcej informacji można znaleźć w tym artykule w dzienniku .
Najważniejsze różnice między zaopatrzeniem i artykułami dziennikarskimi :
źródło
W języku laika
we wzorze strategii nie ma stanów lub wszystkie mają ten sam stan. Wszyscy mają różne sposoby wykonywania zadania, podobnie jak różni lekarze leczą tę samą chorobę tego samego pacjenta z tym samym stanem na różne sposoby.
W stanie wzorca subiektywnie występują stany, takie jak aktualny stan pacjenta (powiedzmy wysoka temperatura lub niska temperatura), na podstawie których zostanie ustalony następny sposób działania (recepty na lek). I jeden stan może prowadzić do innego stanu, więc stan jest do stanu zależności (skład techniczny).
Jeśli technicznie spróbujemy to zrozumieć, na podstawie porównania kodu obu, możemy stracić subiektywność sytuacji, ponieważ oba wyglądają bardzo podobnie.
źródło
Oba wzorce delegują się do klasy podstawowej, która ma kilka pochodnych, ale tylko we wzorcu stanowym te klasy pochodnych zawierają odwołanie do klasy kontekstu.
Innym sposobem spojrzenia na to jest to, że wzorzec strategii jest prostszą wersją wzorca państwowego; wzór podrzędny, jeśli chcesz. To naprawdę zależy, czy chcesz, aby stany pochodne wstrzymywały odwołania do kontekstu, czy nie (tj. Czy chcesz, aby wywoływały metody w kontekście).
Aby uzyskać więcej informacji: Robert C Martin (i Micah Martin) odpowiedz na to w swojej książce „Agile Principles, Patterns and Practices in C #”. ( http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258 )
źródło
To dość stare pytanie, ale wciąż szukałem tych samych odpowiedzi i właśnie to odkryłem.
Dla wzorca stanu rozważmy przykład przycisku Medial Player Play. Kiedy gramy, zaczyna się grać i uświadamia kontekstowi, że gra. Za każdym razem, gdy klient chce wykonać operację gry, sprawdza bieżący stan gracza. Teraz klient wie, że stan obiektu jest odtwarzany za pośrednictwem obiektu kontekstowego, dlatego wywołuje metodę akcji akcji obiektów stanu pauzy. Część klienta realizująca stan i określająca stan, w którym musi wykonać działanie, może zostać zautomatyzowana.
https://www.youtube.com/watch?v=e45RMc76884 https://www.tutorialspoint.com/design_pattern/state_pattern.htm
W przypadku wzorca strategii układ diagramu klas jest taki sam jak wzorzec stanu. Klient przychodzi do tego porozumienia, aby wykonać operację. Oznacza to, że zamiast różnych stanów istnieją różne algorytmy, na przykład różne analizy, które należy wykonać na wzorcu. Tutaj klienci mówią kontekstowi, co chce zrobić, jaki algorytm (niestandardowy algorytm zdefiniowany w biznesie), a następnie wykonuje to.
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
Obie implementują zasadę otwartego zamknięcia, dzięki czemu programista może dodawać nowe stany do wzorca stanu i nowy algorytm.
Różnica polega na tym, że są one używane, a mianowicie wzorzec stanu używany do wykonywania innej logiki w zależności od stanu obiektu. W przypadku strategii inna logika.
źródło
Stan ma trochę zależności w klasach pochodnych stanu: tak jak jeden stan wie o kolejnych stanach, które go następują. Na przykład lato przychodzi po zimie dla dowolnego sezonu lub stan dostawy po stanie depozytu na zakupy.
Z drugiej strony strategia nie ma takich zależności. Tutaj można zainicjować dowolny stan w zależności od typu programu / produktu.
źródło
Różnicę omówiono w http://c2.com/cgi/wiki?StrategyPattern . Wykorzystałem wzorzec strategii, aby umożliwić wybór różnych algorytmów w ramach ogólnych analizy danych. Dzięki temu możesz dodawać algorytmy bez konieczności zmiany ogólnych ram i logiki.
Typowym przykładem jest to, że masz platformę do optymalizacji funkcji. Ramy konfigurują dane i parametry. Wzorzec strategii pozwala wybierać algorytmy, takie jak najtrudniejsze zjazdy, gradienty sprzężone, BFGS itp. Bez zmiany frameworka.
źródło
Zarówno strategia, jak i stan mają taką samą strukturę. Jeśli spojrzysz na diagram klasy UML dla obu wzorców, wyglądają dokładnie tak samo, ale ich intencja jest zupełnie inna. Wzorzec projektu stanu służy do definiowania stanu obiektu i zarządzania nim, natomiast wzorzec strategii służy do definiowania zestawu wymiennych algorytmów i pozwala klientowi wybrać jeden z nich. Tak więc wzorzec strategii jest wzorcem sterowanym przez klienta, podczas gdy obiekt może sam zarządzać stanem.
źródło
Krótko mówiąc, dzięki wzorcowi strategicznemu możemy ustawić pewne zachowanie w locie, przy pomocy wzorca stanu możemy być pewni, że obiekt zmieni swoje zachowanie wewnętrznie wraz ze zmianą swojego stanu.
źródło
Gdy masz projekt, który można podzielić na 2 zadania:
zadanie 1: możesz wykonać jeden z dwóch różnych algorytmów: alg1, alg2
zadanie 2: możesz wykonać jeden z trzech różnych algorytmów: alg3, alg4, alg5
alg1 i alg2 są wymienne; alg3, alg4 i alg5 są wymienne.
Wybór algorytmu do wykonania w zadaniu 1 i zadaniu 2 zależy od stanów:
stan 1: potrzebujesz alg1 w zadaniu 1 i alg3 w zadaniu 2
stan 2: potrzebujesz alg2 w zadaniu 1 i alg5 w zadaniu 2
Kontekst możesz zmienić obiekt stanu ze stanu 1 na stan 2. Wtedy twoje zadanie zostanie wykonane przez alg2 i alg5, zamiast alg1 i alg3.
Możesz dodać więcej wymiennych algorytmów dla zadania 1 lub zadania 2. Jest to wzorzec strategii.
Możesz mieć więcej stanów z różną kombinacją algorytmów w zadaniu 1 i zadaniu 2. Wzorzec stanu pozwala przełączać się z jednego stanu do drugiego i wykonywać różne kombinacje algorytmów.
źródło
„Strategia” to tylko algorytm, który możesz zmienić w różnych okolicznościach w zależności od potrzeb i przetwarza coś dla Ciebie. Dawny. możesz wybrać sposób kompresji pliku. zip lub rar ... w metodzie.
Ale „Stan” MOŻE zmienić całe zachowanie obiektu, gdy się zmieni, Nawet może zmienić inne pola ... dlatego ma odniesienie do swojego właściciela. Należy zauważyć, że zmiana pola obiektu może w ogóle zmienić zachowanie obiektu. Dawny. kiedy zmieniasz State0 na State1 w obj, zmieniasz liczbę całkowitą na 10 .. więc kiedy wywołujemy obj.f0 (), które wykonują pewne obliczenia i używają tej liczby całkowitej, wpływa to na wynik.
źródło