1 Inżynieria oprogramowania Wzorce operacyjne WWW: http://www.fizyka.umk.pl/~jacek/dydaktyka/inzynieria/index.html Jacek Matulewski Instytut Fizyki, UMK WWW: http://www.fizyka.umk.pl/~jacek E-mail: [email protected] semestr letni 2016
2 Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.
3 Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.
4 Główna lektura 2 Dodatkowo wykorzystamy adaptacje do C# wzorców G4 opisane w książce S. J. Metskera
5 Wzorce operacyjne Wzorce dotyczące dzielenia odpowiedzialności między współpracującymi ze sobą obiektami (porządkują złożone przepływy sterowania): Interpreter (Interpreter) Iterator (Iterator) Łańcuch zobowiązań (Chain of responsibility) Mediator (Mediator) Metoda szablonowa (Template method) Obserwator (Observer) Odwiedzający (Visitor) Pamiątka (Memento) Polecenie (Command) Stan (State) Strategia (Strategy)
6 Interpreter (Interpreter) Cel: Stworzenie mini-języka używanego w programie http://zenit.senecac.on.ca/wiki/index.php/Interpreter
7 Interpreter (Interpreter) Implementacja: Tworzona jest klasa główna reprezentująca cały interpreter oraz klasy potomne reprezentujące poszczególne reguły gramatyki. To w efekcie interpretacji łańcucha prowadzi do powstania drzewa syntaktycznego złożonego z obiektów reguł
8 Interpreter (Interpreter) Przykład: liczby w notacji rzymskiej liczbaRzymska ::= {tysiące} {setki} {dziesiątki} {jedności} tysiące, setki, dziesiątki, jedności ::= dziewięć | cztery | {pięć} {jeden} {jeden} {jeden} dziewięć ::= "CM" | "XC" | "IX" cztery ::= "CD" | "XL" | "IV" pięć ::= 'D' | 'L' | 'V' jeden ::= 'M' | 'C' | 'X' | 'I' Nazwy używane w kontekście tego wzorca: InterpreterLiczbRzymskich – wyrażenie abst. InterpreterTysięcy,... – wyrażenie pośrednie liczbyRzymskie – Context (informacje globalne) main – Client
9 Iterator (Iterator) Cel: Umożliwia sekwencyjny dostęp do elementów agregatu bez konieczności eksponowania wewnętrznej struktury. Możliwość iteracji niezależnie/równolegle, różnego typu https://sourcemaking.com/design_patterns/iterator
10 Iterator (Iterator) Standardowe metody iteratora: template class Iterator { public: virtual void First() = 0; virtual void Next() = 0; virtual bool IsDone() = 0; virtual Element CurrentElement() = 0; protected: Iterator(){} }; Ukryty konstruktor – metoda wytwórcza w agregatorze
11 Iterator (Iterator) Implementacja z rozdzieleniem iteratora i agregatu: http://zenit.senecac.on.ca/wiki/index.php/Iterator
12 Iterator (Iterator) Przykład: AbstrakcyjnyStos, Iterator - abstrakcje Stos – prosta implementacja z tablicą do przechow. StosIterator – pozwala na przebiegnięcie wszystkich zapamiętanych elementów (wbrew naturze stosu) Nazwy używane w kontekście tego wzorca: Iterator – Iterator. StosIterator – ConcreteIterator AbstrakcyjnyStos – Aggregate Stos – ConcreteAggregate
13 Iterator (Iterator) W platformie.NET jest interfejs IEnumerable, który kontaktuje metodę GetEnumerator zwracającą iterator implementujący interfejs IEnumerator. Interfejs IEnumerator deklaruje: własność Current zwracającą bieżący elment typu T, metodę MoveNext przesuwającą „karetkę” na następną pozycję (na ostatnim elemencie zwr. false ), metodę Reset przesuwającą karetkę na oryginalną pozycję Pętla foreach, rozszerzenia LINQ
14 Iterator (Iterator) Dostęp do kolekcji.NET z wielu wątków: Problemem pojawia się jeżeli iterator przebiega kolekcję w jednym wątku, a jednocześnie inny wątek ją modyfikuje. Podejścia: 1. Użycie metody Synchronized kolekcji do pobrania kopii kolekcji wrażliwej na zmiany zgłaszamy wyjątek 2. Listę pobieraną przez Synchronized możemy przebiec pętlą for bez użycia iteratora nieaktualna 3. Polecenia lock równocześnie w miejscu użycia iteratora i metodzie pozwalającej na modyfikacje wolne 4. Tworzenie płytkiej kopii kolekcji i iteracja po niej (por. 2)
15 Iterator (Iterator) Iterator dla kompozytu: 4. Tworzenie płytkiej kopii kolekcji i iteracja po niej (por. 2)
16 Iterator (Iterator) Zadania domowe: 1. Niech klasa Kierownik (wzorzec kompozyt) implementuje int. IEnumerable pozwalający na iterowanie po podwładnych. Uwzględnij możliwość obecności cykli. 2. Dla stosu z przykładu ilustrującego wzorzec iterator przygotować dwa alternatywne iteratory: - przeskakujący co dwa elementy, - iterujący od końca tablicy.
17 Łańcuch zobowiązań (Chain of Responsibility) Cel: Osłabienie wiązania klienta zgłaszającego żądanie (request), czyli wywołania metody lub zgłaszanie zdarzenia z obiektem obsługującym (handler) poprzez ustawienie modyfikowalnego zbioru obiektów obsługujących http://zenit.senecac.on.ca/wiki/index.php/Chain_of_Responsibility
18 Łańcuch zobowiązań (Chain of Responsibility) Implementacja: Implementacja podobna do kolejki (ale może być np. kompozyt). Por. do zdarzeń trasowanych (wł. Handled ), haki w WinAPI. Por. z potokiem: ( wyjście = trzy(dwa(jeden(wejście) ). Dowolność w ustawieniu sposbu obsługi (wszystkie, jeden, wybrany) https://sourcemaking.com/design_patterns/chain_of_responsibility
19 Łańcuch zobowiązań (Chain of Responsibility) Wada: Nie ma gwarancji obsłużenia żądania (wśród obiektów może zabraknąć takiego, który potrafi obsłużyć to konkretne żądanie) Klient ostatecznie nie wie, czy żądanie zostanie obsłużone żądanie, czy w ogóle lub ile razy Nazwy używane w kontekście tego wzorca: HandlerBazowy – Handler, obiekt obsługujący, Handler1,.. – ConcreteHandler, obiekt obsługujący main – Client
20 Mediator (Mediator) Cel: Zmniejszyć liczbę powiązań między równorzędnymi elementami systemu (podgrupami). Typowe: GUI, redukcja plątaniny metod zdarzeniowych https://sourcemaking.com/design_patterns/mediator
21 Mediator (Mediator) Cel: Mediator może także pełnić rolę strażnika integralności stanów obiektów zdefiniowanych w kodzie, który ma otaczać (integracja relacji) https://sourcemaking.com/design_patterns/mediator
22 Mediator (Mediator) Przykład: Klasyczna implementacja listy, w której każdy element przechowuje wskaźnik do następnego elementu stwarza problemy przy operacjach: dodawania, wstawiania i usuwania. Aby w ogóle usunąć relacje między elementami listy dodamy organizujący je obiekt – mediator. Nazwy używane w kontekście tego wzorca: Lista – Mediator Nie będzie Mediator vs ConcreteMediator
23 Metoda szablonowa (Template Method) Cel: Implementacja rodziny algorytmów różniących się szczegółami (np. przygotowywanie pizzy: ciasto -> dodatki -> pieczenie). Kontrola procesu pozostaje w klasie abstrakcyjnej. Podstawowa technika polimorfizmu z powtórnym użyciem kodu. http://pl.wikipedia.org/wiki/Metoda_szablonowa_(wzorzec_projektowy)
24 Metoda szablonowa (Template Method) Przygotowywanie pizzy – dwa przykładowe przepisy: (na podstawie referatu Łukasza Kiełczykowskiego) Margherita 1. Przygotuj cienkie ciasto. 2. Dodaj sos pomidorowy. 3. Dodaj mozzarelle. 4. Dodaj bazylię i trochę oliwy. 5. Piecz przez 15 minut. Sycylijska 1. Przygotuj grube ciasto. 2. Dodaj ostry sos. 3. Dodaj oliwki i kapary. 4. Dodaj mieszankę przypraw. 5. Piecz przez 20 minut. Abstrakcja 1. Przygotuj ciasto. 2. Dodaj sos. 3. Połóż dodatki 4. Dodaj przyprawy. 5. Piecz
25 Metoda szablonowa (Template Method) Uwagi: Ciekawe źródło: http://www.objectmentor.com/resources/ articles/inheritanceVsDelegation Czasem można i opłaca się implementację Strategii (podobne algorytmy zaimplementowane w osobnych klasach ze wspólnym interfejsem) zastąpić implementacją opartą na Metodzie Szablonowej. W ten sposób unikamy powielania kodu (DRY). Metody szablonowej zwykle nie można wywołać z konstruktora klasy – zawiera odwołania do metod czysto wirtualnych (chyba, że zadbamy o domyślne implementacje wszystkich metod)
26 Metoda szablonowa (Template Method) Nazwy używane w kontekście tego wzorca: Pizza – AbstractClass, zawiera metodę szablonową Margherita, Sycylijska – ConcreteClass main – Client
27 Obserwator (Observer) Cel: Rozluźnienie wiązania między zależnymi od siebie klasami (dwiema lub wieloma) przez zastąpienie bezpośrednich odwołań relacją publikuj-subskrybuj https://sourcemaking.com/design_patterns/observer
28 Obserwator (Observer) Typowy przykład: model widoku i reagujące na zmiany jego stanu widoki (wzorzec obecny w MVC, MVVM i innych z tej rodziny) Porównaj INotifyPropertyChanged i INotifyCollectionChanged z platformy.NET (WPF) i platformy WinRT Nazwy używane w kontekście tego wzorca: Model – Subject, interfejs podmiotu lub sam podmiot Model1, Model2 – ConcreteSubject (niekonieczne) Widok – Observer, interfejs obserw. z met. Aktualizuj WidokTabela, WidokWykres – ConcreteObserver
29 Obserwator (Observer) Zdarzenia jako implementacja wzorca obserwator: button.Click += new EventHandler(o.metoda) button – instancja obserwabli, źródło danych EventHandler – delegacja, deklaracja typu metody o – inny obiekt, nawet z innej warstwy systemu (ale może być również this ) metoda – obserwator, metoda zdarzeniowa reagująca na zmiany += – subskrypcja powiadamiania o zmianach -= – rezygnacja z subskrypcji
30 Obserwator (Observer) Reactive Extensions (Rx) - biblioteka ułatwiająca programowanie asynchroniczne i oparte na zdarzeniach skupiające się na przepływie danych (powiadamianiu o ich zmianach). Przekazywanie zapytań LINQ. Zarządzanie współbieżnością za pomocą planistów. IObservable, IObserver, ISubject Reactive programming – paradygmat programowania, w którym źródło danych aktywnie powiadamia wyższe warstwy o zmianach np. MVVM (zestawiane z paradygmatem interaktywnym, w którym wyższe warstwy same sprawdzają stan danych, czasem muszą to robić cyklicznie)
31 Odwiedzający (Visitor) Cel: Załóżmy strukturę obiektów, np. kompozyt pracowników. Na każdym pracowniku chcemy wykonać pewną operację zależną od jego typu nie zmieniając za oryginalnych klas. Realizujemy ten cel definiując klasę z metodami Visit osobną dla każdego typu pracownika i przyjmującymi instancję odpowiedniego typu pracownika. W pierwotnych klasach konieczna obecność tylko jednej nowej metody Accept. Klasy z pierwotnego drzewa to elementy Klasa (lub klasy - dla różnych operacji) - odwiedzający
32 Odwiedzający (Visitor) https://sourcemaking.com/design_patterns/visitor
33 Odwiedzający (Visitor) Przykład: wydrukujemy informacje o pracownikach z drzewa (kompozytu) Nazwy używane w kontekście tego wzorca: IPracownik – Element Pracownik, Kierownik – ConcreteElement Odwiedzający – Visitor OdwiedzajacyZliczający – ConcreteVisitor rektor – ObjectStructure
34 Odwiedzający (Visitor) Zalety/Wady: Po zaimplementowaniu wzorca Odwiedzający możemy swobodnie dodawać kolejne czynności realizowane na całej strukturze obiektów. Uogólnienie: Wzorzec Visitor można także traktować jako pozostawienie przez projektanta furtki do nowych funkcjonalności bez konieczności modyfikacji istniejącej hierarchii klas. Wówczas ma sens nie tylko dla struktury obiektów, ale nawet dla jednej klasy.
35 Pamiątka (Memeno) Inna nazwa: Znacznik (Token) Cel: Zapis wewnętrznego stanu innego obiektu (źródła) bez jego udostępniania; opis stanu = pamiątka https://sourcemaking.com/design_patterns/memento
36 Przykład: punkty kontrolne (cofnij/ponów), przechowywanie stanu w aplikacjach mobilnych Nazwy używane w kontekście tego wzorca: Licznik – Originator, źródło PamiątkaLicznika – Memento, pamiątka main – zarządca (np. mechanizm cofania) Pamiątka (Memento)
37 Przykład: wstrzymywanie i wznawianie działania aplik. Trwała pamiątka: zapis stanu np. w pliku (savegame), trwałe punkty kontrolne – odmiana backupu aplikacji Za pamiątkę można uznać efekt serializacji obiektu (nie – jeżeli tylko pola publiczne, np. do XML) Memento wielosesyjne – np. zapis stanu obiektu lub aplikacji w chmurze i przywrócenie jej na innym urządzeniu lub choćby w innej sesji Pamiątka (Memento)
38 Polecenie (Command) Inna nazwa: Akcja (Action), Transakcja (Transaction) Cel: zamyka żądanie/funkcję/metodę w formie obiektu, Umożliwia zapamiętywanie (cofanie) i kolejkowanie żądań. Separuje kod wykonywany od klienta, który użyje efektu. http://zenit.senecac.on.ca/wiki/index.php/Command
39 Polecenie (Command) Realizacja: przechowywanie wskaźnika do funkcji/metody opcja 1: może także przechowywać parametry wywołania opcja 2: dodatkowa akcja sprawdzająca możliwość uruchom. Przykład: Platforma.NET – klasa RelayCommand w MVVM http://zenit.senecac.on.ca/wiki/index.php/Command
40 Pamiątka / Polecenie Zadanie domowe: W aplikacji Notatnik przygotować system Undo/Redo Cofanie (un-do) powinno wykorzystywać pamiątki Ponawianie (re-do) powinno używać polecenia Wprowadź ograniczenie na liczbę możliwych cofnięć Własność Enabled elementów menu Cofnij i Ponów zmieniaj korzystając ze wzorca obserwator.
41 Stan (State) Idea: Skomplikowana funkcjonalność klasy, zależna od parametrów (tj. od aktualnego stanu instancji klasy) rozdzielana jest do osobnych klas reprezentujących funkcjonalność w poszczególnych stanach http://www.silversoft.net/docs/dp/hires/pat5hfso.htm (na podstawie GoF)
42 Stan (State) Realizacja: Klasa główna przechowuje adresy klas reprezentujących poszczególne stany i deleguje na nie wykonanie żądań własnych metod Przykład: TCPConnection (GoF), Drzwi (Stan = DrzwiZamknięte, DrzwiOtwarte ) Nazwy używane w kontekście tego wzorca: Drzwi – Context, klasa udostępniana klientom StanDrzwi – State, stan – interfejs do kapsułkowania zachowania klasy Drzwi w różnych stanach DrzwiZamkniete, DrzwiOtwarte – poszczeg. stany main – klient
43 Strategia (Strategy) Idea: rodzina algorytmów, każdy reprezentowany przez osobną klasę, które mogą być używane zamiennie Eliminuje switch w jakiejś konkretnej metodzie Inne nazwy: Polityka (Policy) https://sourcemaking.com/design_patterns/strategy
44 Strategia (Strategy) Realizacja: Klasa główna przechowuje adres klasy reprezentującej wybrany algorytm i korzysta z jej metod do realizacji konkretnego żądania (wykonania metody). Wzorzec Strategii może być powielony przy wielu metodach https://sourcemaking.com/design_patterns/strategy
45 Strategia (Strategy) Nazwy używane w kontekście tego wzorca: OdgadywaczLiczby – Context, klasa udostępniana StrategiaZgadywaniaLiczby – Strategy, wspólny interfejs dla wielu konkretnych strategii (używanych do realizacji metody OdgadywaczLiczby::Zgaduj ) StrategiaPoKolei, StrategiaLosowo – implementacje poszczególnych algorytmów main – klient
46 Wzorce spoza książki G4 Wzorzec strukturalny Private Class Data https://sourcemaking.com/design_patterns/private_class_data Cała kategoria wzorców współbieżności: http://pl.wikipedia.org/wiki/Wzorzec_projektowy_(informatyka)#Klasyfikacja_rozszerzona Aktywny obiekt, Asynchroniczne sterowanie przez zdarzenia, Udaremnianie, Blokada z podwójnym zatwierdzaniem, Ochraniane wstrzymywanie, Obiekt monitorujący, Blokada zapisu i odczytu, Zarządca procesów, Pula wątków, Pamięć dla wątków, Reaktor; Antywzorce projektowe http://pl.wikipedia.org/wiki/Antywzorzec_projektowy
47 Rozkład MVC na proste wzorce Aktywny model / widok – obserwator (widok obserwuje model) Widok / kontroler – strategia (widok pozostawia obsługę reakcji kontrolerowi) Widok – kompozyt (praca z zagnieżdżonymi widokami) Model WidokKontroler aktualizujemodyfikuje Użytkownik używa jest oglądany
48 Inny podział wzorców Wzorce interfejsów: Adapter, Fasada, Kompozyt, Most Wzorce odpowiedzialności: Singleton, Obserwator, Mediator, Pośrednik, Łańcuch odpowiedzialności, Pyłek Wzorce konstrukcyjne: Budowniczy, Metoda wytwórcza, Fabryka abstrakcyjna, Prototyp, Pamiątka Wzorce operacji: Metoda szablonowa, Stan, Strategia, Polecenie, Interpreter Wzorce rozszerzeń: Dekorator, Iterator, Odwiedzający