Czytałem o zasadzie OCP i jak wykorzystać wzorzec strategii, aby to osiągnąć.
Miałem zamiar spróbować wyjaśnić to kilku osobom, ale jedynym przykładem, jaki przychodzi mi do głowy, jest użycie różnych klas walidacji w oparciu o status „zamówienia”.
Przeczytałem kilka artykułów online, ale zazwyczaj nie opisują one prawdziwego powodu, dla którego warto zastosować tę strategię, na przykład generowania raportów / rachunków / walidacji itp.
Czy są jakieś przykłady z prawdziwego świata, w których uważasz, że wzorzec strategii jest powszechny?
źródło
Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
CipherFactory
może zmylić tych, którzy nie są zaznajomieni z wzorcem strategii.Ponownie, stary post, ale nadal pojawia się w wyszukiwaniach, więc dodam jeszcze dwa przykłady (kod jest w C #). Absolutnie uwielbiam wzorzec Strategii, ponieważ oszczędził mi to wiele razy, kiedy kierownicy projektów mówią: „Chcemy, aby aplikacja działała„ X ”, ale„ X ”nie jest jeszcze jasne i może się zmienić w najbliższej przyszłości. " W tym filmie objaśniającym wzorzec strategii jako przykład wykorzystano StarCraft.
Rzeczy, które należą do tej kategorii:
Sortowanie: chcemy posortować te liczby, ale nie wiemy, czy będziemy używać BrickSort, BubbleSort czy innego sortowania
Walidacja: Musimy sprawdzić pozycje zgodnie z „Jakaś regułą”, ale nie jest jeszcze jasne, jaka będzie ta reguła i możemy wymyślić nowe.
Gry: Chcemy, aby gracz chodził lub biegał, gdy się porusza, ale być może w przyszłości powinien również umieć pływać, latać, teleportować się, kopać pod ziemią itp.
Przechowywanie informacji: chcemy, aby aplikacja przechowywała informacje w bazie danych, ale później może być konieczne zapisanie pliku lub nawiązanie połączenia internetowego
Wyprowadzanie: musimy wypisać X jako zwykły ciąg, ale później może to być CSV, XML, JSON itp.
Przykłady
Mam projekt, w którym użytkownicy mogą przypisywać produkty do osób w bazie danych. To przypisanie produktu do osoby ma status „Zatwierdzony” lub „Odrzucony”, który jest zależny od pewnych reguł biznesowych. Na przykład: jeśli użytkownik przypisuje produkt osobie w określonym wieku, jego status powinien zostać odrzucony; Jeśli różnica między dwoma polami w elemencie jest większa niż 50, jego status jest odrzucony itp.
Teraz, w momencie opracowywania, te reguły biznesowe nie są jeszcze całkowicie jasne, a nowe zasady mogą pojawić się w dowolnym momencie. Potęga wzorca stragety polega na tym, że utworzyłem RuleAgent, który otrzymuje listę IRules.
W momencie przypisania produktu do osoby, tworzę RuleAgent, podaję mu listę reguł (z których wszystkie implementują IRule) i proszę o walidację przypisania. Przejdzie przez wszystkie swoje zasady. Który, ponieważ wszystkie implementują ten sam interfejs, wszystkie mają
IsApproved
metodę i zwracają false, jeśli którykolwiek z nich zwróci false.Teraz, na przykład, nagle pojawia się kierownik i mówi, że musimy również odrzucić wszystkie zadania dla stażystów lub wszystkie zadania dla osób pracujących w nadgodzinach ... Tworzysz nowe zajęcia w ten sposób:
Widzisz, że nie musisz ciągle dodawać ani usuwać instrukcji if lub kodu, po prostu utwórz nową klasę reguł, która implementuje interfejs IRUle i wyłączaj je w razie potrzeby.
Kolejny świetny przykład: seria filmów Scotta Allena pod adresem http://www.asp.net/mvc/pluralsight, gdzie używa wzorca strategii w części aplikacji poświęconej testom jednostkowym
Tworzy witrynę internetową, która ma stronę wyświetlającą pozycje w oparciu o popularność. Jednak „Popularne” może oznaczać wiele rzeczy (większość wyświetleń, większość subskrybentów, data utworzenia, największa aktywność, najmniejsza liczba komentarzy itp.), A kierownictwo nie wie jeszcze dokładnie, jak zamówić, i może chcieć eksperymentować z różnymi zamówienia w późniejszym terminie. Tworzysz interfejs (IOrderAlgorithm lub coś w tym rodzaju) za pomocą metody zamówienia i pozwalasz obiektowi Orderer delegować porządkowanie na konkretną implementację interfejsu IOrderAlgorithm. Możesz utworzyć „CommentOrderer”, „ActivityOrderer”, itd. I po prostu wyłączaj je, gdy pojawią się nowe wymagania.
źródło
InternRule
teraz, ale w jaki sposób uruchamiamyOvertimeRule
? W jaki sposób możemy zapewnić, że jakakolwiek logika nazywa sięOvertimeRule.IsApproved
teraz, również wywołujeInternRule.IsApproved
?Kluczowe uwagi:
Strategia jest wzorcem projektowania behawioralnego. Służy do przełączania się między rodziną algorytmów.
Ten wzorzec zawiera jeden abstrakcyjny interfejs strategii i wiele konkretnych implementacji strategii ( algorytmów ) tego interfejsu.
Aplikacja korzysta tylko z interfejsu strategii . W zależności od niektórych parametrów konfiguracyjnych, konkretna strategia zostanie oznaczona jako interfejs .
Diagram UML z Wikipedii
Przykład prawdziwego słowa: linie lotnicze oferujące zniżki w niektórych miesiącach (lipiec-grudzień) . Możesz mieć jeden moduł Opłaty , który decyduje o opcjach cenowych w zależności od numeru miesiąca.
Spójrz na prosty przykład. Ten przykład można rozszerzyć na aplikacje do sprzedaży detalicznej online, które z łatwością zapewniają rabaty na artykuły w koszyku w specjalne dni / happy hours.
wynik:
Przydatne artykuły:
wzór strategii autorstwa dzone
wzorzec strategii poprzez pozyskiwanie źródeł
źródło
Przychodzi mi do głowy kilka dość prostych przykładów:
Kompresja danych. Możesz mieć interfejs ICompressor, którego jedyna metoda wygląda mniej więcej tak:
byte [] kompresja (bajt [] wejście);
Twoje konkretne klasy kompresji mogą być takie jak RunLengthCompression, DeflateCompression itp.
źródło
Jednym z powszechnych zastosowań wzorca strategii jest definiowanie własnych strategii sortowania (w językach bez funkcji wyższego rzędu), np. Sortowanie listy ciągów według długości w Javie, przekazując anonimową klasę wewnętrzną (implementacja interfejsu strategii):
W podobny sposób można zastosować strategie do zapytań natywnych z obiektowymi bazami danych, np. W db4o:
źródło
Mam aplikację, która codziennie synchronizuje swoją bazę użytkowników z naszym katalogiem korporacyjnym. Użytkownicy kwalifikują się lub nie kwalifikują się na podstawie ich statusu na Uniwersytecie. Każdego dnia program obsługi administracyjnej przechodzi i upewnia się, że te, które mają się kwalifikować, są obsługiwane w aplikacji, a te, które nie są, są usuwane (w rzeczywistości zgodnie z wdzięcznym algorytmem degradacji, ale to nie ma znaczenia). W sobotę robię dokładniejszą aktualizację, która synchronizuje niektóre właściwości każdego użytkownika, a także upewniam się, że mają one odpowiednie uprawnienia. Pod koniec miesiąca przetwarzam zwrot rachunków w oparciu o wykorzystanie w tym miesiącu.
Używam komponowalnego wzorca strategii, aby wykonać tę synchronizację. Program główny zasadniczo wybiera strategię główną w zależności od dnia tygodnia (synchronizacja tylko zmian / synchronizacja wszystkich) i czasu semestru w stosunku do kalendarza akademickiego. Jeśli cykl rozliczeniowy dobiega końca, komponuje go również ze strategią rozliczeniową. Następnie uruchamia wybraną strategię za pośrednictwem standardowego interfejsu.
Nie wiem, jak często się to zdarza, ale czułem, że idealnie pasuje do wzorca strategii.
źródło
Wiem, że to stare pytanie, ale myślę, że mam inny ciekawy przykład, który niedawno wdrożyłem.
Jest to bardzo praktyczny przykład wzorca strategii stosowanego w systemie dostarczania dokumentów.
Miałem system dostarczania PDF, który otrzymał archiwum zawierające wiele dokumentów i kilka metadanych. Na podstawie metadanych zdecydował, gdzie umieścić dokument; powiedzmy, w zależności od danych, mogę zapisać dokument
A
,B
lubC
magazynowych systemów lub mieszankę tych trzech.Różni klienci korzystali z tego systemu i mieli różne wymagania dotyczące wycofywania / obsługi błędów w przypadku błędów: jeden chciał, aby system dostarczania zatrzymał się przy pierwszym błędzie, zostawił wszystkie dokumenty już dostarczone w swoich magazynach, ale zatrzymał proces i nie dostarczał niczego innego ; inny chciał, żeby
B
w przypadku błędów przy składowaniu został wycofanyC
, ale zostawił to, co zostało już dostarczoneA
. Łatwo sobie wyobrazić, że trzeci czy czwarty też będzie miał inne potrzeby.Aby rozwiązać ten problem, utworzyłem podstawową klasę dostarczania, która zawiera logikę dostarczania oraz metody wycofywania danych ze wszystkich magazynów. Metody te nie są w rzeczywistości wywoływane bezpośrednio przez system dostarczania w przypadku błędów. Zamiast tego klasa używa Dependency Injection, aby otrzymać klasę „Rollback / Error Handling Strategy” (opartą na kliencie korzystającym z systemu), która jest wywoływana w przypadku błędów, która z kolei wywołuje metody wycofywania zmian, jeśli jest to odpowiednie dla tej strategii.
Klasa dostawy sama zgłasza, co się dzieje w klasie strategii (jakie dokumenty zostały dostarczone do jakich magazynów i jakie awarie się wydarzyły), a gdy wystąpi błąd, pyta strategię, czy kontynuować, czy nie. Jeśli strategia mówi „stop it”, klasa wywołuje metodę „cleanUp” strategii, która używa wcześniej zgłoszonych informacji, aby zdecydować, które metody wycofywania wywołać z klasy dostarczającej lub po prostu nic nie robić.
Więc mam teraz dwie różne strategie: jedna to
QuitterStrategy
(która kończy pracę po pierwszym błędzie i nic nie czyści), a druga toMaximizeDeliveryToAStrategy
(która stara się jak najbardziej nie przerywać procesu i nigdy nie przywracać zawartości dostarczonej do pamięci)A
, ale wycofuje rzeczy z,B
jeśli dostawa sięC
nie powiedzie).Z mojego zrozumienia jest to jeden z przykładów wzorca strategii. Jeśli (tak, czytasz) myślisz, że się mylę, skomentuj poniżej i daj mi znać. Ciekawi mnie, co oznaczałoby „czyste” wykorzystanie wzorca strategii i jakie aspekty mojej realizacji naruszają definicję. Myślę, że wygląda to trochę zabawnie, ponieważ interfejs strategii jest nieco gruby. Wszystkie przykłady, które widziałem do tej pory, wykorzystują tylko jedną metodę, ale nadal uważam, że zawiera ona algorytm (jeśli część logiki biznesowej można uznać za algorytm, a myślę, że tak jest).
Ponieważ strategia jest również powiadamiana o zdarzeniach podczas realizacji dostawy, można ją również uznać za obserwatora , ale to już inna historia.
Po przeprowadzeniu krótkich badań wydaje się, że jest to „wzorzec złożony” (jak MVC, wzorzec wykorzystujący wiele wzorców projektowych pod spodem w określony sposób) zwany Doradcą . Jest doradcą, czy dostarczanie powinno być kontynuowane, czy nie, ale jest również aktywną obsługą błędów, ponieważ może wycofać dane, gdy zostanie o to poproszony.
W każdym razie, jest to dość złożony przykład, który może sprawić, że poczujesz, że użycie wzorca strategii jest zbyt proste / głupie. W połączeniu z innymi wzorami może być naprawdę złożony i jeszcze bardziej przydatny.
źródło
Wzorzec strategii jest najczęściej używanym wzorcem, szczególnie w przypadku algorytmów walidacji i sortowania.
Pozwólcie, że wyjaśnię na prostym praktycznym przykładzie
Kod testowy to
Ten sam przykład pochodzi z http://coder2design.com/strategy-pattern/
źródło
Dobrym przykładem wzorca strategii może być gra, w której możemy mieć różne postacie, a każda postać może mieć wiele broni do ataku, ale jednocześnie może używać tylko jednej broni. Mamy więc postać jako kontekst, na przykład King, Commander, Knight, Soldier i broń jako strategię, w której attack () może być metodą / algorytmem zależnym od używanej broni. Więc jeśli konkretnymi klasami broni były Sword, Axe, Crossbow, BowAndArrow itp., Wszystkie zaimplementowałyby metodę attack (). Jestem pewien, że dalsze wyjaśnienia nie są potrzebne.
źródło
Zastosowałem podejście strategiczne w dość złożonym silniku w aplikacji, która jest dobrym przykładem. Zasadniczo rola silnika polegała na znalezieniu najpierw listy osób, które miały widżet, a drugą rolą było ustalenie, którzy byli 10 najlepszych ludzi z widżetem na podstawie nieznanej liczby parametrów (np. , ilość w magazynie, opcje wysyłki itp. itd. itd.)
Zasadniczo podzieliliśmy problem na dwie strategie, z których pierwsza polegała na pobieraniu danych, ponieważ wiedzieliśmy, że mamy wiele źródeł naszych widżetów i musimy mieć możliwość uzyskania danych i przekształcenia ich we wspólną strukturę.
Potem zdaliśmy sobie również sprawę, że mamy wiele algorytmów, niektóre oparte na ważeniu parametrów, inne były bardzo dziwne i właściwe, i nie mogłem im oddać sprawiedliwości bez wyciągania wizualizacji i wykresów. wybór najlepszych ludzi.
Nasza usługa sama w sobie polegała na tym, że zasadniczo definiowała dane wejściowe, wyjściowe i przeprowadzała pewną normalizację danych, a także wykorzystywała wzorzec dostawcy do podłączenia dostawców danych specyficznych dla aplikacji i dostawców algorytmów, którzy używali strategii. To był dość skuteczny system.
Odbyliśmy kilka debat, czy używamy strategii lub wzorca szablonu, którego nigdy nie rozwiązaliśmy.
źródło
Czy na pewno status „zamówienia” nie jest wzorcem stanu? Mam przeczucie, że zamówienie nie będzie obsługiwane inaczej w zależności od jego statusu.
Weźmy na przykład metodę Wysyłka na zamówienie:
Najlepszy przykład wzorca stanu (i innych wzorów), jaki znalazłem, był w książce „ Head First Design Patterns ”, co jest niesamowite. Na drugim miejscu pojawi się seria szablonów w blogach Davida Cumpsa .
źródło
Powiedzmy, że chcesz napisać algorytm do obliczania n-tego X dnia danego miesiąca i roku, np. Drugiego poniedziałku października 2014 r. Chcesz użyć klasy Time Androida
android.text.format.Time
do reprezentowania daty, ale chcesz również napisać ogólny algorytm to może również dotyczyćjava.util.Calendar
.To właśnie zrobiłem.
W DatetimeMath.java:
W TimeMath.java:
W OrdinalDayOfWeekCalculator.java, klasa z algorytmem ogólnym:
W mojej aplikacji na Androida nazwałbym coś takiego
Jeśli chcę ponownie użyć tego samego algorytmu
java.util.Calendar
, po prostu napisałbym klasę CalendarMath, która implementuje trzy metody w DatetimeMath, a następnie użyłbymźródło
źródło
Kilka tygodni temu dodałem wspólny interfejs Java, który został zaimplementowany przez jeden z naszych obiektów domeny. Ten obiekt domeny został załadowany z bazy danych, a reprezentacja bazy danych była schematem gwiazdy z ponad 10 gałęziami. Jedną z konsekwencji posiadania tak ciężkiego obiektu domeny jest to, że musieliśmy stworzyć inne obiekty domeny, które reprezentowały ten sam schemat, chociaż były mniej ciężkie. Dlatego sprawiłem, że inne lekkie obiekty implementują ten sam interfejs. Inaczej mówiąc mieliśmy:
Pierwotnie chciałem użyć
CollectibleElephant
do sortowaniaElephant
s. Dość szybko moi koledzy z drużyny wpadli na to,CollectibleElephant
aby przeprowadzić kontrole bezpieczeństwa, filtrować je, gdy są wysyłane do GUI itp.źródło
Musieliśmy stworzyć interfejs obsługi administracyjnej innej firmy dla platformy korporacyjnej z bardzo skomplikowaną bazą danych. Dostarczenie danych do dostarczenia było listą naszych typów danych, które zostały umieszczone w kolejce priorytetowej w naszej aplikacji, aby mogły zostać zapisane w bazie danych we właściwej kolejności ze względu na zależności.
Proces zapisywania tych danych był wtedy dość prosty, wyskakuj z góry kolejki priorytetów, a następnie wybierz strategię opartą na typie wyodrębnionego obiektu.
źródło
Z Wikipedii
W aplikacji Windows Paint można zobaczyć wzorzec strategii, w którym można niezależnie wybrać kształt i kolor w różnych sekcjach. Tutaj kształt i kolor to algorytmy, które można zmieniać w czasie wykonywania.
Jeśli chcesz narysować okrąg w kolorze czerwonym, zamiast oferować opcję „RedCircle”, pozwalają one wybrać okrąg i wybrany kolor.
Bez wzorca strategii zwiększy się liczba klas z iloczynem kartezjańskim kształtu i koloru. Również interfejs zmienia się dla każdej implementacji.
źródło
Wyobraź sobie na przykład strzelankę z wrogami AI. Chcesz, aby nieustannie walczyli na różne sposoby w zależności od tego, co się dzieje. Dzięki wzorowi strategii możesz w sposób ciągły zapętlać i dynamicznie zmieniać sposób wykonania określonej czynności lub działania.
źródło