Jacek Matulewski Instytut Fizyki UMK WWW http www

  • Slides: 180
Download presentation
Jacek Matulewski Instytut Fizyki, UMK WWW: http: //www. fizyka. umk. pl/~jacek E-mail: jacek@fizyka. umk.

Jacek Matulewski Instytut Fizyki, UMK WWW: http: //www. fizyka. umk. pl/~jacek E-mail: jacek@fizyka. umk. pl Wzorce projektowe w C# WWW: http: //www. fizyka. umk. pl/~jacek/dydaktyka/inzynieria/index. html semestr letni 2016

Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.

Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.

Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.

Główna lektura 1 Głównym materiałem źródłowym jest książka tzw. gangu czworga pt. „Wzorce projektowe”.

Główna lektura 2 Dodatkowo wykorzystamy adaptacje do C# wzorców G 4 opisane w książce

Główna lektura 2 Dodatkowo wykorzystamy adaptacje do C# wzorców G 4 opisane w książce S. J. Metskera

Warunki zaliczenia 1. Warunek konieczny: Odrobienie zadań domowych (może być w parach). 2. Kolokwium

Warunki zaliczenia 1. Warunek konieczny: Odrobienie zadań domowych (może być w parach). 2. Kolokwium (ocena) 3. Ocenę można dodatkowo podnieść biorąc udział w konkursach (zwykle nagroda to +1/2 do oceny). Zadania: http: //www. fizyka. umk. pl/~jacek/dydaktyka/inzynieria/2016 L/zadania. txt Konkursy – w prezentacji

Programowanie obiektowe Zagadnienia na powtórzeniu: • klasy, pola, metody, własności, • zakres dostępności (prywatny,

Programowanie obiektowe Zagadnienia na powtórzeniu: • klasy, pola, metody, własności, • zakres dostępności (prywatny, publiczny, chroniony) • dziedziczenie, klasy abstrakcyjne (figury), • nadpisywanie metod • przykład: równanie kwadratowe (double, Complex) • testy jednostkowe, refactoring, TDD • biblioteki DLL

Interfejs (ang. interface) C++: interfejs = klasa abstrakcyjna (ale tylko metody czysto wirtualne) class

Interfejs (ang. interface) C++: interfejs = klasa abstrakcyjna (ale tylko metody czysto wirtualne) class IFigura { public: virtual double Oblicz. Pole() = 0; virtual double Oblicz. Obwod() = 0; }; class Prostokat : public IFigura { private: double a, b; public: Prostokat(double a, double b) { this->a = a; this->b = b; } double Oblicz. Pole() { return a * b; } double Oblicz. Obwod() { return 2 * a + 2 * b; } };

Interfejs (ang. interface) C++: interfejs = klasa abstrakcyjna (ale tylko metody czysto wirtualne) Prostokat

Interfejs (ang. interface) C++: interfejs = klasa abstrakcyjna (ale tylko metody czysto wirtualne) Prostokat std: : cout prostokat(2, 3); << "Pole: " << prostokat. Oblicz. Pole() << "n"; << "Obwod: " << prostokat. Oblicz. Obwod() << "n"; Prostokat* pprostokat = new Prostokat(2, 3); std: : cout << "Pole: " << pprostokat->Oblicz. Pole() << "n"; std: : cout << "Obwod: " << pprostokat->Oblicz. Obwod() << "n"; std: : cout << "n"; IFigura* pfigura = new Prostokat(2, 3); std: : cout << "Pole: " << pfigura->Oblicz. Pole() << "n"; std: : cout << "Obwod: " << pfigura->Oblicz. Obwod() << "n"; std: : cout << "n";

Interfejs (ang. interface) C#: można nadal używać klas abstrakcyjnych w roli interfejsów public abstract

Interfejs (ang. interface) C#: można nadal używać klas abstrakcyjnych w roli interfejsów public abstract class Figura { public abstract double Oblicz. Pole(); public abstract double Oblicz. Obwód(); } class Prostokąt : Figura { private double a, b; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public override double Oblicz. Pole() { return a * b; } public override double Oblicz. Obwód() { return 2 * a + 2 * b; } };

Interfejs (ang. interface) C#: można nadal używać klas abstrakcyjnych w roli interfejsów Prostokąt prostokąt

Interfejs (ang. interface) C#: można nadal używać klas abstrakcyjnych w roli interfejsów Prostokąt prostokąt = new Prostokąt(2, 3); Console. Write. Line("Pole: " + prostokąt. Oblicz. Pole()); Console. Write. Line("Obwod: " + prostokąt. Oblicz. Obwód()); Console. Write. Line(); Figura figura = new Prostokąt(2, 3); Console. Write. Line("Pole: " + figura. Oblicz. Pole()); Console. Write. Line("Obwod: " + figura. Oblicz. Obwód()); Console. Write. Line();

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) public

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) public interface IFigura { double Oblicz. Pole(); double Oblicz. Obwód(); } class Prostokąt : IFigura { private double a, b; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public override double Oblicz. Pole() { return a * b; } public override double Oblicz. Obwód() { return 2 * a + 2 * b; } };

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) Prostokąt

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) Prostokąt prostokąt = new Prostokąt(2, 3); Console. Write. Line("Pole: " + prostokąt. Oblicz. Pole()); Console. Write. Line("Obwod: " + prostokąt. Oblicz. Obwód()); Console. Write. Line(); IFigura figura = new Prostokąt(2, 3); Console. Write. Line("Pole: " + figura. Oblicz. Pole()); Console. Write. Line("Obwod: " + figura. Oblicz. Obwód()); Console. Write. Line();

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) public

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) public interface IFigura { double Pole { get; } //własności double Obwód { get; } } class Prostokąt : IFigura { private double a, b; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public double Pole { get { return a * b; } } public double Obwód { get { return 2 * a + 2 * b; } } };

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) Prostokąt

Interfejs (ang. interface) C#: specjalna konstrukcja pozwalająca na definiowanie interfejsów (słowo kluczowe interface) Prostokąt prostokąt = new Prostokąt(2, 3); Console. Write. Line("Pole: " + prostokąt. Pole); Console. Write. Line("Obwod: " + prostokąt. Obwód); Console. Write. Line(); IFigura figura = new Prostokąt(2, 3); Console. Write. Line("Pole: " + figura. Pole); Console. Write. Line("Obwod: " + figura. Obwód); Console. Write. Line();

Interfejs (ang. interface) Interfejs vs klasa abstrakcyjna Interfejs można zastąpić klasą abstrakcyjną, w której

Interfejs (ang. interface) Interfejs vs klasa abstrakcyjna Interfejs można zastąpić klasą abstrakcyjną, w której są tylko metody abstrakcyjne Interfejs vs delegacja (typ wskaźnika do metody) Delegacja to typ metody = wymaganie metody lub klasy względem używającego ją kodu Interfejs określa sygnatury metod, w tym i ich nazwy = kontrakt klasy dostarczającej Rola interfejsów: Ograniczenie (rozluźnienie) związków między klasami. Ustalenie kontraktów między nimi. Jednocześnie prowadzi jednak do uwolnienia ich rozwoju, o ile przestrzegamy kontraktu.

Użycie interfejsów - zasady SOLID Spopularyzował: Robert C. Martin (uncle Bob) (jeden z sygnatariuszy

Użycie interfejsów - zasady SOLID Spopularyzował: Robert C. Martin (uncle Bob) (jeden z sygnatariuszy Agile Manifesto) Cel: przygotowanie kodu, który jest łatwy do utrzymania (konserwacji), rozbudowy i prawd. zmian wymagań

Zasady SOLID S. Zasada jednej odpowiedzialności Single responsibility principle (SRP) O. Zasada otwarte-zamknięte Open/close

Zasady SOLID S. Zasada jednej odpowiedzialności Single responsibility principle (SRP) O. Zasada otwarte-zamknięte Open/close principle (OCP) L. Zasada podstawienia Liskov substitution principle (LSP) I. Zasada segregacji interfejsów Interface segregation principle (ISP) D. Zasada odwrócenia zależności Dependency inversion principle (DIP)

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Boska klasa, którą

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Boska klasa, którą należy rozdzielić na wiele klas odpowiedzialnych tylko za pojedyncze funkcjonalności Zmiana jednej funkcjonalności pociąga za sobą konieczność zmiany wielu innych (wszystko splątane) Inne sformułowanie: KISS Keep it simple, Stupid!

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Przykład dla klas

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Przykład dla klas implementujących figury (np. Prostokąt): Odpowiedzialności: - przechowywanie rozmiaru do obliczeń P i O (double), - przechowywanie położenia do rysowania (int), - obliczenia pola i obwodu, - rysowanie z System. Drawing. Graphics. Zmiana sposobu rysowania (np. Win. Forms -> WPF) oznacza konieczność zmiany tej klasy i klas zależnych

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public interface IFigura

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public interface IFigura //tu wymieszana odpowiedzialność modelu i widoku { double Pole { get; } double Obwód { get; } void Rysuj(Graphics g, Color kolor, double skala = 1, bool wypełnij = false); } public class Prostokąt : IFigura { private int x, y; private double a, b; public Prostokąt(int x, int y, double a, double b) {. . . } public double Pole { get { return a * b; } } public double Obwód { get { return 2 * a + 2 * b; } } public void Rysuj(Graphics g, Color kolor, double skala = 1, . . . ) {. . . } }

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Zmiana: - przygotowanie

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle Zmiana: - przygotowanie klasy odpowiedzialnej za obliczenia, - przeniesienie kodu odpowiedzialnego za rysowanie do osobnej klasy lub do statycznego „pomocnika” Efekt: rozdzielenie warstw modelu i widoku Zmiana sposobu rysowania dotknie tylko klasy widoku (stosowanie zasady SRP nie musi prowadzić do tworzenia warstw, ale warstwy są efektem konsekwentnego stosowania SRP)

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public interface IFigura

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public interface IFigura { double Pole { get; } double Obwód { get; } void Rysuj(Graphics g, Color kolor, double skala = 1, bool wypełnij = false); } public class Prostokąt : IFigura { private int x, y; private double a, b; public Prostokąt(int x, int y, double a, double b) {. . . } public double Pole { get { return a * b; } } public double Obwód { get { return 2 * a + 2 * b; } } public void Rysuj(Graphics g, Color kolor, double skala = 1, . . . ) {. . . } }

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public static class

Zasady SOLID Zasada jednej odpowiedzialności (klasy, metody, DLL) Single responsibility principle public static class Pomocnik. Rysowania //helper { public static void Rysuj(this Model. Prostokąt prostokąt, int x, int y, Graphics g, Color kolor, double skala = 1, bool wypełnij = false) { int w = (int)(skala * prostokąt. A); int h = (int)(skala * prostokąt. B); if (!wypełnij) g. Draw. Rectangle(new Pen(kolor), x, y, w, h); else g. Fill. Rectangle(new Solid. Brush(kolor), x, y, w, h); } public static void Rysuj(this Model. IFigura figura, int x, int y, Graphics g, Color kolor, double skala = 1, bool wypełnij = false) {. . . }

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Klasy są otwarte na rozszerzenia, ale zamknięte na

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Klasy są otwarte na rozszerzenia, ale zamknięte na modyfikacje To dotyczy też metod/funkcji oraz modułów, czy bibliotek. Idea kodu produkcyjnego, który nie może być zmieniany (poza naprawianiem błędów) „Do dodania możliwości założenia kapelusza nie powinna być potrzebna operacja mózgu!”

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Rozwiązania tego pozornego paradoksu: - wprowadzenie abstrakcji umożliwiających

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Rozwiązania tego pozornego paradoksu: - wprowadzenie abstrakcji umożliwiających „podmianę” kodu na inny bez modyfikacji zasadniczej klasy (interfejsy, „wstrzykiwanie” kodu), - dodanie lub zmiana funkcjonalności w klasie potomnej. Zasada OCP wymaga projektowania kodu w sposób ułatwiający jego późniejszą rozbudowę

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Przykład: - klasy reprezentujące prostokąt i okrąg -

Zasady SOLID Zasada otwarte-zamknięte Open/close principle Przykład: - klasy reprezentujące prostokąt i okrąg - Statyczny pomocnik obliczający pola poszczególnych figur (za obliczanie pól w pełni odpowiedzialny jest pomocnik) Problem (jak zwykle w przypadku SOLID): Jak napisać kod w taki sposób, żeby był łatwy do rozbudowy?

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public class Prostokąt { public double A {

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public class Prostokąt { public double A { get; private set; } public double B { get; private set; } public Prostokąt(double a, double b) { A = a; B = b; } } public class Okrąg { public double R{ get; private set; } public Okrąg(double r) { R = r; } }

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public static class Sumator. Pól. Figur { public

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public static class Sumator. Pól. Figur { public static double Sumuj. Pola. Figur(object[] figury) { double suma. Pól = 0; foreach(object figura in figury) Ukryta zależność { if(figura is Prostokąt) { Prostokąt prostokąt = figura as Prostokąt; suma. Pól += prostokąt. A * prostokąt. B; }. . . } return suma. Pól; } od klas Prostokąt, … Klient: rozszerzyć zbiór figur o nowe Dodajemy kolejny if i polecenia zależ.

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public interface IFigura { double Pole { get;

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public interface IFigura { double Pole { get; } } Interfejs = abstrakcja public class Prostokąt : IFigura { public double A { get; private set; } public double B { get; private set; } public Prostokąt(double a, double b) { A = a; B = b; } public double Pole { get { return a * b; } } } Klasy figur przejmują odpowiedzialność za obliczanie figur

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public static class Sumator. Pól. Figur { public

Zasady SOLID Zasada otwarte-zamknięte Open/close principle public static class Sumator. Pól. Figur { public static double Sumuj. Pola. Figur(IFigura[] figury) { double suma. Pól = 0; foreach(IFigura figura in figury) { suma. Pól += figura. Pole; Bez instrukcji warunkowych } return suma. Pól; } Klient: rozszerzyć zbiór figur o nowe Dodajemy nową klasę impl. IFigura

Zasady SOLID Zasada podstawiania Liskov subsitution principle Funkcje które używają wskaźników lub referencji do

Zasady SOLID Zasada podstawiania Liskov subsitution principle Funkcje które używają wskaźników lub referencji do klas bazowych, muszą być w stanie używać również obiektów klas dziedziczących po klasach bazowych, bez dokładnej znajomości tych obiektów. Idea standaryzacji: baterie AA = R 6, AAA = R 03, … Interfejsy jako specyfikacje standardów

Zasady SOLID Zasada podstawiania Liskov subsitution principle Z zasady LSP wynika, że klasa potomna

Zasady SOLID Zasada podstawiania Liskov subsitution principle Z zasady LSP wynika, że klasa potomna powinna rozszerzać funkcjonalność klasy bazowej, a nie ją zawężać lub całkowicie zmieniać. Sposób użycia klasy potomnej powinien być taki sam, jak klasy bazowej. Pełna wymienność klas potomnych, ale również klasa bazowa powinna móc zastąpić klasę potomną

Zasady SOLID Zasada podstawiania Liskov subsitution principle public class Prostokąt { protected double a

Zasady SOLID Zasada podstawiania Liskov subsitution principle public class Prostokąt { protected double a = 0, b = 0; public virtual double A { get { return a; } set { a = value; } } public virtual double B { get { return b; } set { b = value; } } public double Pole { get { return a * b; } } } public class Kwadrat : Prostokąt //ta klasa nie rozszerza klasy bazowej { public override double A { get { return a; } set { a = value; b = value; } } public override double B { get { return b; } set { a = value; b = value; } } }

Zasady SOLID Zasada podstawiania Liskov subsitution principle public static double ZmieńBoki. IOblicz. Pole(Prostokąt prostokąt,

Zasady SOLID Zasada podstawiania Liskov subsitution principle public static double ZmieńBoki. IOblicz. Pole(Prostokąt prostokąt, double a, b) { prostokąt. A = a; prostokąt. B = b; return prostokąt. Pole; } Wynik wywołania: Pole (prostokąt): 6, pole (kwadrat): 9 Spodziewamy się, że instancja klasy potomnej może być przesłana z równym skutkiem, jak instancja klasy bazowej.

Zasady SOLID Zasada podstawiania Liskov subsitution principle public interface IFigura { double Pole {

Zasady SOLID Zasada podstawiania Liskov subsitution principle public interface IFigura { double Pole { get; } } public class Prostokąt : IFigura { protected double a = 0, b = 0; public virtual double A { get { return a; } set { a = value; } } public virtual double B { get { return b; } set { b = value; } } public double Pole { get { return a * b; } } } public class Kwadrat : IFigura //Klasa Kwadrat nie dziedziczy po Prostokąt { public override double A { get { return a; } set { a = value; b = value; } } public override double B { get { return b; } set { a = value; b = value; } } public double Pole { get { return a * a; } } }

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Redukcja zależności między klasami: związki między

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Redukcja zależności między klasami: związki między klasami powinny być ograniczone do minimum, czyli klient klasy powinien mieć dostęp tylko do tych składowych, których rzeczywiście potrzebuje Klasa: Prostokąt Klasa-klient: Kalkulator. Pola, Kalkulator. Obwodu

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Po co? Co się stanie w

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Po co? Co się stanie w przypadku zmiany klasy Prostokąt lub klas-klientów? Jak ograniczyć zmiany w całym kodzie? Kontrakty między klasami = interface’y Klasa: Prostokąt Klasa-klient: Kalkulator. Pola, Kalkulator. Obwodu

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle public interface IFigura { double Pole

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle public interface IFigura { double Pole { get; } double Obwód { get; } } public class Prostokąt : IFigura { protected double a = 0, b = 0; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public double Pole { get { return a * b; } } public double Obwód { get { return 2 * a + 2 * b; } } }

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle //klasa Sumator. Pól. Figur public static

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle //klasa Sumator. Pól. Figur public static double Oblicz. SumęPól(IEnumerable<IFigura> figury) { double suma. Pól = 0; foreach (IFigura figura in figury) suma. Pól += figura. Pole; return suma. Pól; } //klasa Sumator. Obwodów. Figur public static double Oblicz. SumęObwodów(IEnumerable<IFigura> figury) { double suma. Obwodów = 0; foreach (IFigura figura in figury) suma. Obwodów += figura. Obwód; return suma. Obwodów; }

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Osobne interfejsy na poszczególne funkcjonalności (kontrakty

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle Osobne interfejsy na poszczególne funkcjonalności (kontrakty z klientami ograniczają zakres zmian): public interface IFigura. ZPolem { double Pole { get; } } public interface IFigura. ZObwodem { double Obwód { get; } } public class Prostokąt : IFigura. ZPolem, IFigura. ZObwodem { protected double a = 0, b = 0; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public double Pole { get { return a * b; } } public double Obwód { get { return 2 * a + 2 * b; } } }

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle //klasa Sumator. Pól. Figur public static

Zasady SOLID Zasada segregacji interfejsów Interface segregation principle //klasa Sumator. Pól. Figur public static double Oblicz. SumęPól(IEnumerable<IFigura. ZPolem> figury) { double suma. Pól = 0; foreach (IFigura. ZPolem figura in figury) suma. Pól += figura. Pole; return suma. Pól; } //klasa Sumator. Obwodów. Figur public static double Oblicz. SumęObwodów(IEnumerable<IFigura. ZObwodem> figury) { double suma. Obwodów = 0; foreach (IFigura. ZObwodem figura in figury) suma. Obwodów += figura. Obwód; return suma. Obwodów; }

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle Oczywista oczywistość: Niższe warstwy architektoniczne nie

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle Oczywista oczywistość: Niższe warstwy architektoniczne nie mogą zależeć od wyższych! DIP: Zależność wyższych warstw od niższych też powinna być ograniczona jedynie do kontaktów (interfejsów) W przypadku zmian w module takie osłabienie wiązania ogranicza zakres koniecznych zmian w innych modułach. Zapewnia wymienność modułów z niższej warstwy.

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle //niższa warstwa public class Prostokąt {

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle //niższa warstwa public class Prostokąt { private double a, b; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public double Pole { get { return a * b; } } } //wyższa warstwa (klasa silnie zależna od klasy Prostokąt) public class Opakowanie { private Prostokąt prostokąt = null; public Opakowanie(double a, double b) { prostokąt = new Prostokąt(a, b); } public double Oblicz. Pole() { return prostokąt. Pole; } }

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle Silna zależność klasy Opakowanie od klasy

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle Silna zależność klasy Opakowanie od klasy Prostokąt: • nie można wymienić klasy podrzędnej na inną • w razie zmian w którejkolwiek z klasy, druga musi także być modyfikowana Zasada DIP: • Moduły z wyższej warstwy nie powinny zależeć od modułów z niższej warstwy. Oba powinny zależeć od abstrakcji (np. interfejsu) • Abstrakcja nie powinna zależeć od szczegółów (np. a, b), to szczegóły powinny zależeć od abstrakcji (nie ma ich w interf. )

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle public interface IFigura. ZPolem { double

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle public interface IFigura. ZPolem { double Pole { get; } } //abstrakcja //niższa warstwa (zależy od abstrakcji) public class Prostokąt : IFigura { private double a, b; public Prostokąt(double a, double b) { this. a = a; this. b = b; } public double Pole { get { return a * b; } } } //wyższa warstwa (metoda zależy tylko od abstrakcji) public class Opakowanie { private IFigura. ZPolem figura = null; public Opakowanie(IFigura. ZPolem figura) {this. figura = figura; } public double Oblicz. Pole() { return figura. Pole; } }

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle W przypadku zmian w module takie

Zasady SOLID Zasada odwrócenia zależności Dependency inversion principle W przypadku zmian w module takie osłabienie wiązania ogranicza zakres koniecznych zmian w innych modułach. Zapewnia wymienność modułów z niższej warstwy. Rozwiązanie, które zastosowaliśmy to Dependency Injection (wstrzyknięcie zależności). Można wstrzyknąć obiekt przez konstruktor, własność lub do jednej konkretnej metody, która używa zależności. Uwaga! W ogólności DI ≠ Io. C ≠ DIP (DI ϵ Io. C ϵ DIP)

Zasady SOLID usuwanie zależności między klasami ogólność (wymienność klas) i podatność na zmiany Dependency

Zasady SOLID usuwanie zależności między klasami ogólność (wymienność klas) i podatność na zmiany Dependency Inversion Principle (DIP) – osłabianie (decoupling) zależności klas z wyższych warstw od klas z niższych Design by Contract (programowanie poprzez kontakt) – metodyka tworzenie systemów, w których kładzie się nacisk na zasady SOLID Inversion of Control (Io. C, odwrócenie sterowania) – przenoszenie części odpowiedzialności poza klasę np. klient tworzący klasę Opakowanie ma kontrolę nad sposobem obliczania figury (może przekazać taką implementację interfejsu IFigura. ZPolem jaką zechce, dowolnie obliczającą pole figury). Dependency Injection (wstrzykiw. zależności) – jedna z realizacji Io. C

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Ekspert (Information Expert) Pytanie: Której klasie przypisać odpowiedzialność/zadanie? Odpowiedź: Tej, która ma niezbędne informacje (aby uniknąć przekazywania danych i związanych z tym powiązań między klasami) Przykład skróconego opisu: http: //nandrew. blogspot. com/2007/09/zasady-grasp-cz-i. html http: //nandrew. blogspot. com/2007/09/zasady-projektowania-obiektowego-grasp. html Zasady zebrane przez Craiga Larmana w książce Wzorce Go. F można traktować jako konsekwencję stosowania zasad GRASP

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Twórca (Creator) Pytanie: Która klasa powinna tworzyć obiekt jakiejś klasy Klasa? Odpowiedź: Ta klasa, która: - przechowuje kolekcje klas Klasa, - jest mocno powiązana z klasą Klasa, - ma dane niezbędne do inicjacji instancji Klasa. Im więcej przesłanek, tym lepsza decyzja.

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Kontroler (Controller) Pytanie: Jaki obiekt (z warstwy modelu) powinien obsługiwać żądania użytkownika (np. przesyłane z warstwy widoku / GUI)? Odpowiedź: klasa kontrolera powinna: - opisywać działanie systemu jako całości (spinać go), - reprezentować urządzenie, na którym działa system, - reprezentować przypadek użycia ( Generalnie: powinna to być klasa, która organizuje pracę systemu.

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Niska liczba powiązań (Low Coupling) Wysoka spójność (High Cohesion) Pytanie: Jak zmniejszyć powiązania między klasami systemu? Jak nie przeciążać klasę obowiązkami? Odpowiedź: Każda klasa powinna mieć tylko jedno zadanie (jedną odpowiedzialność), ale na tyle obszerne, żeby nie wymagało współpracy z innymi klasami (unikanie powiązań między klasami). Porównaj z: Single Responsibility Principle i boskie klasy

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Pośrednictwo (Indirection) Pytanie: Jak ograniczyć powiązania między dwoma pakietami klas? Odpowiedź: Wstawić między te pakiety dodatkową klasę, która przejmie odpowiedzialność za komunikację i tłumaczenie danych, wywołania metod przekazywanych między obydwoma pakietami To sprzyja zasadom Niskiej liczby powiązań i Wysokiej spójności Przykład: Warstwa dostępowa (DAL) między bazą danych i BLL Efekt: BLL nie zależy od sposobu zapisywania danych

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie

Zasady GRASP General Responsibility Assignment Software Principles zasady mówiące o podziale odpowiedzialności w systemie komp. Polimorfizm (Polymorphism) Przejmowanie odpowiedzialności w przypadku alternatywnych możliwości -> alternatywne klasy zgodne z tym samym interfejsem Zapewniona zmienność (Protected Variations) Jak zaprojektować system z łatwo wymienialnymi modułami? Klasy podejrzewane o duże zmiany w przyszłości (niestabilne) zapośredniczyć interfejsami – łatwo będzie je wymienić na inne Czysty wymysł (Pure Fabrication) Wyjście awaryjne, gdy pozostałe zasady dają sprzeczne zalecenia Klasa (np. singleton) realizująca jedynie usługi na rzecz innych klas

Dodatek: Agile Manifesto Odkrywamy nowe metody programowania dzięki praktyce w programowaniu i wspieraniu w

Dodatek: Agile Manifesto Odkrywamy nowe metody programowania dzięki praktyce w programowaniu i wspieraniu w nim innych. W wyniku naszej pracy, zaczęliśmy bardziej cenić: • ludzi i interakcje od procesów i narzędzi • działające oprogramowanie od szczegółowej dokumentacji • współpracę z klientem od negocjacji umów, • reagowanie na zmiany od realizacji założonego planu. Oznacza to, że elementy wypisane po prawej są wartościowe, ale większą wartość mają dla nas te, które wypisano po lewej. JM: To że jesteśmy zwinni i chętni do zmian, nie oznacza, że nie http: //www. agilemanifesto. org/iso/pl/ każemy sobie płacić za dodatkowe godziny spędzone nad kodem.

SCRUM Scrum Guide (ok. 20 stron, także po polsku) Ken Schwaber i Jeff Sutherland

SCRUM Scrum Guide (ok. 20 stron, także po polsku) Ken Schwaber i Jeff Sutherland http: //www. scrumguides. org/ Ken Schwaber Uwaga! Słabe tłumaczenie

SCRUM Tradycyjne metodologie wytwarzania oprogramowania dążą do szczegółowej kontroli całego procesu, w tym kontroli

SCRUM Tradycyjne metodologie wytwarzania oprogramowania dążą do szczegółowej kontroli całego procesu, w tym kontroli przydzielania zadań członkom zespołu oraz długoterminowego planowania prac, a następnie skrupulatnego rozliczania z postępów realizacji planu (por. kontrola lotów samolotów, odpowiedzialni są kontrolerzy r. l. ) Załamanie scentralizowanej kontroli i systemu przydziału zadań wraz ze wzrostem złożoności projektów informatycznych Scrum (jedna z metodologii zwinnych, agile) – zaufanie do zespołu, skrócenie okresów produkcji do sprintów (krótsza perspektywa), plan zastąpiony przez zaległości produktowe (backlog, spis zadań), zaangażowanie klienta – częste wydania z nowymi funkcjonalnościmi (por. proste zasady ruchu drogowego, odpowiedzialny jest kierowca)

SCRUM Empiryczna kontrola procesu wytwarzania oprogramowania sposób na poradzenie sobie ze złożonością nieprzewidywalnością Widoczność

SCRUM Empiryczna kontrola procesu wytwarzania oprogramowania sposób na poradzenie sobie ze złożonością nieprzewidywalnością Widoczność – projekt jest przejrzysty dla kierownictwa i dla klienta. Żadne problemy nie są ukrywane, jasne kryterium „zakończone”. Inspekcja – częsta kontrola wszystkich aspektów rozwijanego oprogramowania i samego procesu (np. przeglądy jakości kodu) Adaptacja – natychmiastowe wdrożenie zaleceń inspektora, aktualizowanie priorytetów przed każdym sprintem (przebiegiem) W SCRUM nie ma etapu szczegółowej analizy, przygotowywania SRS. Już do pierwszego przebiegu z klientem wybierana jest konkretna funkcjonalność, która powinna zostać zaimplementowana po msc.

SCRUM Codzienne spotkania na stojąco (daily scrum) Ich cel to zabranie się do pracy,

SCRUM Codzienne spotkania na stojąco (daily scrum) Ich cel to zabranie się do pracy, a nie myślenie o pracy Zaległości produktu wybrane do implementacji w danej iteracji Sprint (przebieg, iteracja) od 2 tyg. do miesiąca Dziennik Zaległości (sortowany według aktual. priorytetów) http: //www. methodsandtools. com/archive. php? id=18 Struktura SCRUM = przyrostowe iteracje Przyrost funkcjonalności produktu (możliwy do wdrożenia)

SCRUM to iteracyjna metoda przyrostowa wytwarzania oprogramowania Reguły SCRUM: 1. reguła sashimi – każdy

SCRUM to iteracyjna metoda przyrostowa wytwarzania oprogramowania Reguły SCRUM: 1. reguła sashimi – każdy przyrost będący efektem pracy zespołu podczas sprintu musi być w pełni ukończony (def. „zrobione”), co obejmuje analizy, dokumentację, testy, itd. dla tego fragmentu produktu. - Tylko działające oprogramowanie (produkt) jest miarą postępu projektu. - Klient ocenia przydatność (do jego celów biznesowych) kolejnych, w pełni funkcjonalnych wydań produktu. - Jeżeli przyrost nieukończony, to braki wpisywane są do zaległości.

SCRUM Dziennik zaległości (backlog) jest stale sortowany zgodnie z aktualnymi priorytetami klienta. Może być

SCRUM Dziennik zaległości (backlog) jest stale sortowany zgodnie z aktualnymi priorytetami klienta. Może być zmieniany. Nie powinno się jednak zmieniać celów aktualnego sprintu ( kryzysowe przerwanie sprintu powinno być sytuacją wyjątkową) Reguły SCRUM: 2. brak zewnętrznego wpływu na przebieg sprintu, samoorganizacja ( skupienie na ustalonej pracy) 3. możliwa zmiana priorytetów zespołu podczas planowania sprintu ( najwyżej 14 -30 dni straty)

SCRUM Świnie i kurczaki http: //www. implementingscrum. com/cartoons/

SCRUM Świnie i kurczaki http: //www. implementingscrum. com/cartoons/

SCRUM Role w SCRUM (świnie): Właściciel produktu – zadania: - zbiera początkowe i ogólne

SCRUM Role w SCRUM (świnie): Właściciel produktu – zadania: - zbiera początkowe i ogólne wymagania, - ustala (nieostateczną) wizję gotowego produktu (zwrot inwestycji) - ustala plan wydań i akceptuje produkt wytworzony w przebiegu, - zarządza dziennikiem zaległości produktowych (w tym sortowaniem zadań zgodnie z aktualnymi priorytetami) Odpowiedzialność za: zwrot kosztów inwestycji produktu – wybór funkcjonalności, które rozwiązują problemy biznesowe klienta ( sortowanie zaległości)

SCRUM Role w SCRUM (świnie): Zespół – optymalnie składa się z 5 -9 osób

SCRUM Role w SCRUM (świnie): Zespół – optymalnie składa się z 5 -9 osób - zespół sam ustala cel przebiegu (biorąc pod uwagę priorytety), - autonomicznie rozdziela prace między siebie, - dba o jakość kodu (inspekcje, rewizje), - zmienia zaległości produktowe w nowe funkcjonalności produktu, - pod koniec przebiegu prezentuje efekty właścicielowi produktu Odpowiedzialność: Zespół jest w pełni odpowiedzialny za zarządzanie samym sobą! W zespole nie ma hierarchii lub innej struktury, która utrudniałaby komunikację. To nie znaczy, że nie uznaje się doświadczenia i stażu. Zarządzanie = przeprowadzanie inspekcji (emp. kontr. ) adaptacja

SCRUM Role w SCRUM (świnie): Scrum Master – nie jest kierownikiem projektu (project manager)

SCRUM Role w SCRUM (świnie): Scrum Master – nie jest kierownikiem projektu (project manager) - nie kieruje zespołem – zespół sam się organizuje, - nie sprawdza postępów prac i nie rozdaje dziennych zadań, - zamiast szefa jest raczej trenerem (także właściciela produktu), - pilnuje przestrzegania zasad SCRUM, pomaga wdrażać SCRUM, - dba o warunki pracy, usuwa przeszkody (techniczne i społeczne), zarządza kryzysami i konfliktami, chroni zespół przed utrudnieniami - chroni zespół przed właścicielem produktu i działem marketingu, ale również dba o dobrą komunikację z właścicielem produktu - dba o otwartość i prawdziwość informacji o postępie prac, informuje wszystkie strony (także kurczaki) o ew. trudnościach, - dba o integrację zespołu

SCRUM Role w SCRUM: Właściciel produktu Zespół Scrum Master http: //www. ioz. pwr. wroc.

SCRUM Role w SCRUM: Właściciel produktu Zespół Scrum Master http: //www. ioz. pwr. wroc. pl/pracownicy/kuchta/Joanna_P%C 5%82 askonka_Scrum. pdf

SCRUM Role w SCRUM (świnie): Ken Schwaber: Ważnym zadaniem Scrum Mastera jest dbanie o

SCRUM Role w SCRUM (świnie): Ken Schwaber: Ważnym zadaniem Scrum Mastera jest dbanie o to, żeby zespół i właściciel produktu skupiali się na tym, co może zostać zrobione, a nie przeżywali frustracji z powodu rzeczy, które aktualnie mogą być wykonane. SCRUM to „sztuka rzeczy możliwych”. Ważne jest ograniczenie perspektywy czasowej do 30 dni: - pozwala zespołowi na skupienie się na bieżących zadaniach, ogranicza chaos zadań, krótkoterminowe plany działania, - utrzymuje zainteresowanie udziałowców projektem (widzą efekty i mają wpływ na wybieranie celów kolejnych iteracji)

SCRUM Daily scrum – prowadzone przez Scrum Mastera codzienne spotkanie przed rozpoczęciem pracy, nie

SCRUM Daily scrum – prowadzone przez Scrum Mastera codzienne spotkanie przed rozpoczęciem pracy, nie dłuższe niż kwadrans (mogą być prowadzone na stojąco przy tablicy Kanban) Scrum Master zadaje każdemu członkowi zespołu trzy pytania: 1. Co zrobiłeś od ostatniego codziennego spotkania Scrum? 2. Co zrobisz do następnego spotkania (zobowiązanie)? 3. Co przeszkadza Ci w pracy? Uwaga! To nie oznacza, że Scrum Master: 1. Sprawdza i ocenia postępy prac 2. Przydziela zadania na kolejny dzień 3. Bezpośrednio wspiera zespół w tworzeniu kodu Celem spotkania jest zabranie się do pracy, a nie myślenie o pracy W razie problemów: spotkanie w mniejszych grupach po daily scrum

SCRUM Kurczaki – obserwatorzy: Wszystkie osoby zainteresowane sukcesem projektu, w tym: - zarząd firmy,

SCRUM Kurczaki – obserwatorzy: Wszystkie osoby zainteresowane sukcesem projektu, w tym: - zarząd firmy, - dział marketingu, - klienci (finansujący projekt), - przyszli użytkownicy produktu. Nie są zaangażowani w wytwarzanie oprogramowania. W trakcie sprintu kontakt z kurczakami poprzez właściciela produktu. Plan sprintu/całego procesu: - Jakich zmian oczekują klienci po zakończeniu sprintu/procesu? - Jakie są postępy po ostatnim sprincie? - Weryfikacja opłacalności inwestycji i wiarygodności zespołu.

Tablica Kanban (jap. ) = widoczny spis KANBAN oznacza też metodologię prowadzenia projektów (por.

Tablica Kanban (jap. ) = widoczny spis KANBAN oznacza też metodologię prowadzenia projektów (por. Toyota Management System), w której kładzie się nacisk na ograniczenie bezczynności pracowników i ograniczenie zapasów. https: //pl. wikipedia. org/wiki/Tablica_kanban http: //www. xqa. com. ar/visualmanagement/2009/06/kanban-boards/

SCRUM Raporty ze sprintów – pełna przejrzystość Wspólna dla świń i kurczaków definicja „zrobione”

SCRUM Raporty ze sprintów – pełna przejrzystość Wspólna dla świń i kurczaków definicja „zrobione” Po sprincie cztery raporty (mogą być zwykłe arkusze, bez opisów): 1. Lista zaległości produktu sprzed ostatniego sprintu 2. Aktualna lista zaległości produktu (po bieżącym sprincie) 3. Raport zmian (szczegółowa lista różnic 2. – 1. ) 4. Wygasający raport zaległości produktowych (może być w postaci wykresu wypalania, burnout chart)

SCRUM Przebieg sprintu w SCRUM: 1. Planowanie sprintu 2. Sprint (w tym codzienne spotkania)

SCRUM Przebieg sprintu w SCRUM: 1. Planowanie sprintu 2. Sprint (w tym codzienne spotkania) 3. Przegląd sprintu 4. Retrospekcja

SCRUM Przebieg sprintu w SCRUM: 1. Planowanie sprintu – pierwszy dzień cyklu, maksymalnie 8

SCRUM Przebieg sprintu w SCRUM: 1. Planowanie sprintu – pierwszy dzień cyklu, maksymalnie 8 godz. a. określenie zaległości produktowych (maks. 4 godz. ) b. ustalenie zaległości dla najbliższego sprintu (zobowiązanie zesp. ) Obecni: właściciel, Scrum Master, zespół, zaproszone kurczaki Efekt: lista zadań do najbliższego sprintu

SCRUM Przebieg sprintu w SCRUM: 2. Sprint – maksymalnie 30 dni (minimum dwa tygodnie)

SCRUM Przebieg sprintu w SCRUM: 2. Sprint – maksymalnie 30 dni (minimum dwa tygodnie) - realizacja przez zespół zobowiązań, zakaz ingerencji - codzienne spotkania (tylko zespół i Scrum Master) Efekt: gotowy do wdrożenia produkt z nową funkcjonalnością

SCRUM Przebieg sprintu w SCRUM: 3. Przegląd sprintu – ostatni dzień cyklu, maksymalnie 4

SCRUM Przebieg sprintu w SCRUM: 3. Przegląd sprintu – ostatni dzień cyklu, maksymalnie 4 godz. - przygotowanie do przeglądu – ok. 1 godz. - prezentacja właścicielowi produktu i kurczakom wykonanej funkcjonalności (prezentowane jest tylko to, co w pełni „zrobione”) - to jest czas na komentarze i krytykę udziałowców (kurczaków)

SCRUM Przebieg sprintu w SCRUM: 4. Retrospekcja – ostatni dzień cyklu, maksymalnie 3 godz.

SCRUM Przebieg sprintu w SCRUM: 4. Retrospekcja – ostatni dzień cyklu, maksymalnie 3 godz. - tylko członkowie zespołu (już po wyjściu kurczaków) - Co poszło dobrze podczas sprintu? Co może zostać poprawione? Cel: poprawienie funkcjonowania zespołu i wdrożenia SCRUM

Przykładowy projekt: „Labirynt” • Aplikacja konsolowa zaprojektowana zgodnie ze wzorcem architektonicznym MVC, czyli Model-View-Controler

Przykładowy projekt: „Labirynt” • Aplikacja konsolowa zaprojektowana zgodnie ze wzorcem architektonicznym MVC, czyli Model-View-Controler • Model – dane i logika labiryntu • Widok – moduł rysujący Użytkownik używa jest oglądany labirynt w konsoli • Kontroler – przyjmuje Kontroler Widok wejście z klawiatury, modyfikuje aktualizuje modyfikuje model Model

Architektura MVC Kontrola oraz przepływ informacji między modułami aplikacji w architekturze MVC Użytkownik używa

Architektura MVC Kontrola oraz przepływ informacji między modułami aplikacji w architekturze MVC Użytkownik używa jest oglądany Kontroler Widok modyfikuje aktualizuje Model

Architektura MVC • Jest wiele wersji samego MVC (+ MVP) • My zaimplementujemy wersję

Architektura MVC • Jest wiele wersji samego MVC (+ MVP) • My zaimplementujemy wersję z pasywnymi modelem i widokiem (passive) oraz nadzorującym kontrolerem (supervising) lepiej pasujący do konsoli Użytkownik (bez zdarzeń) używa jest oglądany • Kontrolera zredukujemy aktualizuje Kontroler Widok do funkcji main modyfikuje Model

Przykładowy projekt: „Labirynt”

Przykładowy projekt: „Labirynt”

Model (klasa Labirynt) Pasywny model przechowujący stan aplikacji VC++: Solution Explorer, View Class Diagram

Model (klasa Labirynt) Pasywny model przechowujący stan aplikacji VC++: Solution Explorer, View Class Diagram

Model (klasa Labirynt) Klasy modelu (C++) class Miejsce. WLabiryncie { public: virtual Rezultat. Próby.

Model (klasa Labirynt) Klasy modelu (C++) class Miejsce. WLabiryncie { public: virtual Rezultat. Próby. Wejścia Spróbuj. Wejść() = 0; virtual int Wejdź(int indeks. Bieżącej. Komórki) { return -1; } virtual bool Otwórz() { return false; } }; class Komórka : public Miejsce. WLabiryncie {. . . enum Rezultat. Próby. Wejścia { Nieokreślony = 0, Powodzenie, Nie. Można. Wejść, Zamknięte }; enum Kierunek { Północ = 0, Południe = 1, Wschód = 2, Zachód = 3 }; enum Stan. Gry { Niezakończona = 0, Śmierć, Wygrana };

Model (klasa Labirynt) Klasy modelu (C++) class Komórka : public Miejsce. WLabiryncie { private:

Model (klasa Labirynt) Klasy modelu (C++) class Komórka : public Miejsce. WLabiryncie { private: int indeks; Miejsce. WLabiryncie* sąsiednie. Miejsca[4]; public: Komórka(int indeks); Miejsce. WLabiryncie* Pobierz. Miejsce. Po. Stronie(Kierunek kierunek) const; void PowiążZMiejscem(Kierunek kierunek, Miejsce. WLabiryncie* miejsce); virtual Rezultat. Próby. Wejścia Spróbuj. Wejść(); virtual int Wejdź(int indeks. Bieżącej. Komórki); int Pobierz. Indeks(); bool Otwórz. Drzwi(Kierunek kierunek); bool Otwórz. Drzwi(); };

Model (klasa Labirynt) Klasy modelu (C++) class Labirynt { private: int liczba. Komórek; PKomórka*

Model (klasa Labirynt) Klasy modelu (C++) class Labirynt { private: int liczba. Komórek; PKomórka* komórki; int indeks. Bieżącej. Komórki, indeks. Celu; Stan. Gry stan. Gry = Niezakończona; public: Labirynt(int liczba. Komórek, int indeks. Początkowej. Komórki, int indeks. Celu); ~Labirynt(); void Dodaj. Komórkę(int indeks, Komórka* komórka); Komórka* Pobierz. BieżącąKomórkę(); Rezultat. Próby. Wejścia PrzejdźWKierunku(Kierunek kierunek); void Zakończ(); Stan. Gry Pobierz. Stan. Gry(); };

Widok (klasa Widok) Klasa widoku (zbiór funkcji bez własnego stanu) #pragma once #include "Model.

Widok (klasa Widok) Klasa widoku (zbiór funkcji bez własnego stanu) #pragma once #include "Model. h" class Widok { private: Labirynt* model; public: Widok(Labirynt* model); static void Wyświetl. InformacjęOKomórce(Komórka* komórka); void Wyświetl. InformacjęOBieżącej. Komórce() const; static void Wyświetl. InformacjęOPróbie. Przejścia. WKierunku(Kierunek kierunek); void Wyświetl. InformacjęORezultacie. Próby. Przejścia(Rezultat. Próby. Wejścia) const; void Wyświetl. InformacjęOPróbie. Otwarcia. Drzwi() const; void Wyświetl. InformacjęORezultacie. Próby. Otwarcia. Drzwi(bool wynik) const; void Wyświetl. InformacjęOStanie. Gry() const; };

Kontroler (funkcja main) #pragma once #include "Model. h" #include "Widok. h" class Kontroler {

Kontroler (funkcja main) #pragma once #include "Model. h" #include "Widok. h" class Kontroler { protected: Labirynt* model; Widok* widok; void Spróbuj. Przejść(Kierunek kierunek); void Spróbuj. OtworzyćDrzwi(); public: Kontroler(void); ~Kontroler(void); void Uruchom(); };

Funkcja main widzi tylko kontroler. Kontroler tworzy instancje modelu i widoku: #include "Kontroler. h"

Funkcja main widzi tylko kontroler. Kontroler tworzy instancje modelu i widoku: #include "Kontroler. h" int main(int argc, char* argv[]) { Kontroler kontroler; kontroler. Uruchom(); return 0; }

Przykładowy projekt: „Labirynt” Piszemy kod C#…

Przykładowy projekt: „Labirynt” Piszemy kod C#…

Przykładowy projekt: „Labirynt” Zadania domowe / dwa konkursy (1 -3, 4): 1. Do widoku

Przykładowy projekt: „Labirynt” Zadania domowe / dwa konkursy (1 -3, 4): 1. Do widoku dodać funkcję rysującą bieżącą komórkę (ściany np. za pomocą znaków *) 2. Przygotować alternatywny widok pokazujący całą mapę z bieżącą komórką oznaczoną # 3. Przygotować zestaw testów jednostkowych dla modelu i widoku (100% pokrycia) 4. Przygotować alternatywny widok korzystający z Open. GL (konkurs)

Wzorce konstrukcyjne Wzorce pozwalające oddzielić proces tworzenia instancji obiektów od jego definicji: • Budowniczy

Wzorce konstrukcyjne Wzorce pozwalające oddzielić proces tworzenia instancji obiektów od jego definicji: • Budowniczy (Builder) • Fabryka abstrakcyjna (Abstract Factory) • Metoda wytwórcza (Factory Method) • Prototyp (Prototype) • Singleton (Singleton)

Budowniczy (Builder) • Założenia: Model posiada klasę organizującą (Labirynt) oraz kilka klas dodatkowych (Komórka,

Budowniczy (Builder) • Założenia: Model posiada klasę organizującą (Labirynt) oraz kilka klas dodatkowych (Komórka, Ściana, itd. ) • Cel: 1. Wydzielenie kodu służącego do budowy złożonego produktu (u nas obiektu modelu) z jego klasy 2. Przesłonięcie szczegółów implementacji modelu (tzw. reprezentacji wewnętrznej). 3. Korzystanie z różnych budowniczych prowadzi do tworzenia różnych produktów bez zmiany kodu funkcji tworzącej i zasadniczej struktury produktu

Budowniczy (Builder) • Implementacja: Do modelu dodana zostaje klasa służąca tylko do stopniowego budowania

Budowniczy (Builder) • Implementacja: Do modelu dodana zostaje klasa służąca tylko do stopniowego budowania złożonej instancji głównej klasy modelu. Po zmianach ważne będą już tylko dwie klasy modelu: Labirynt i Budowniczy. Labiryntu • Nazwy używane w kontekście tego wzorca: Kontroler – Director, kierownik Budowniczy. Labiryntu – Builder, budowniczy Std. Budowniczy. Labiryntu – Concrete Builder Labirynt – Product, produkt

Budowniczy (Builder) http: //zenit. senecac. on. ca/wiki/index. php/Builder

Budowniczy (Builder) http: //zenit. senecac. on. ca/wiki/index. php/Builder

Budowniczy (Builder) http: //zenit. senecac. on. ca/wiki/index. php/Builder

Budowniczy (Builder) http: //zenit. senecac. on. ca/wiki/index. php/Builder

Budowniczy (Builder) Zadania domowe (1) i konkursy (2, 3): 1. Przygotować budowniczego labiryntu, który

Budowniczy (Builder) Zadania domowe (1) i konkursy (2, 3): 1. Przygotować budowniczego labiryntu, który zamiast tworzyć labirynt jedynie liczy komórki i drzwi, a na końcu wyświetla uzyskane liczby. 2. Ukryj w przestrzeni klasy tworzące tzw. wewnętrzną reprezentację (klasy inne niż Labirynt i klasę zawierającą budowniczego). 3. Przygotować budowniczego dla labiryntu złożonego z foremnych trójkątów na zamkniętym pasie. Użyć PBC w jednym kierunku (konkurs).

Metoda wytwórcza (Factory method) • Założenia: W odróżnieniu od budowniczego chcemy zmieniać nie zawartość

Metoda wytwórcza (Factory method) • Założenia: W odróżnieniu od budowniczego chcemy zmieniać nie zawartość złożonego produktu, a móc wybierać między różnymi klasami produktu • Cel: 1. Interfejs do tworzenia różnych produktów (ale bez tworzenia nowej klasy wytwórcy) 2. Możliwość rozszerzania o nowe typy produktów 3. Stworzenie wiele „wirtualnych konstruktorów” dla szczegółowych klas modelu

Metoda wytwórcza (Factory method) • Implementacja: W klasie kontrolującej aplikację (u nas w kontrolerze)

Metoda wytwórcza (Factory method) • Implementacja: W klasie kontrolującej aplikację (u nas w kontrolerze) stworzymy metody tworzące elementy labiryntu i sam labirynt. Klasa zawierająca metody – Wytwórca. • Można tworzyć klasy potomne Wytwórcy/Kontrolera zmieniając zasady gry i modyfikując elementy labiryntu • Nazwy używane w kontekście tego wzorca: Kontroler – Creator, wytwórca Standardowy. Kontroler – Concrete creator Labirynt - Product Standardowy. Labirynt – Concrete product

Metoda wytwórcza (Factory method) http: //zenit. senecac. on. ca/wiki/index. php/Factory_Method

Metoda wytwórcza (Factory method) http: //zenit. senecac. on. ca/wiki/index. php/Factory_Method

Fabryka abstrakcyjna (Abstract factory) • Założenia: W odróżnieniu od budowniczego chcemy zmieniać nie zawartość

Fabryka abstrakcyjna (Abstract factory) • Założenia: W odróżnieniu od budowniczego chcemy zmieniać nie zawartość złożonego produktu, a móc wybierać między różnymi klasami produktu (= metoda wytw. ) • Cel: 1. Zebranie metod wytwórczych dla rodziny produktu w jednej klasie (często singletonie) 2. Stworzenie interfejsu do tworzenia obiektów (fabryka abstrakcyjna) z możliwością jej nadpisywania w fabryce konkretnej

Fabryka abstrakcyjna (Abstract factory) • Implementacja: Tworzymy nową klasę zawierającą zbiór metod wytwórczych tworzących

Fabryka abstrakcyjna (Abstract factory) • Implementacja: Tworzymy nową klasę zawierającą zbiór metod wytwórczych tworzących poszczególne elementy labiryntu • Nazwy używane w kontekście tego wzorca: Fabryka. Labiryntu – Abstract factory Standardowa. Fabryka. Labiryntu – Concrete factory, fabryka konkretna Labirynt – Abstract product Standardowy. Labirynt – Concrete product Kontroler – Client

Fabryka abstrakcyjna (Abstract factory) http: //zenit. senecac. on. ca/wiki/index. php/Abstract_Factory

Fabryka abstrakcyjna (Abstract factory) http: //zenit. senecac. on. ca/wiki/index. php/Abstract_Factory

Singleton (Singleton) • Założenia: Możliwe jest utworzenie tylko jednej instancji klasy • Implementacja: Stworzymy

Singleton (Singleton) • Założenia: Możliwe jest utworzenie tylko jednej instancji klasy • Implementacja: Stworzymy klasę potomną fabryki abstrakcyjnej, która będzie przechowywała prototypy i zwracała ich kopie na żądanie

Singleton (Singleton) http: //zenit. senecac. on. ca/wiki/index. php/Singleton Prywatna instancja klasy Ukryty (chroniony) konstruktor

Singleton (Singleton) http: //zenit. senecac. on. ca/wiki/index. php/Singleton Prywatna instancja klasy Ukryty (chroniony) konstruktor Metoda pozwalająca na pobranie jednej, przechowywanej instancji Inny sposób implementacji: klasa zawierająca wyłącznie statyczne pola i metody

Singleton (Singleton) Przykładowy kod C++: #pragma once class Singleton { private: static Singleton* instancja;

Singleton (Singleton) Przykładowy kod C++: #pragma once class Singleton { private: static Singleton* instancja; protected: Singleton() {}; //ukryty konstruktor public: static Singleton* Pobierz. Instancję() { if (instancja == 0) //lazy initialization instancja = new Singleton(); return instancja; } };

Singleton (Singleton) Przykładowy kod C#: class Singleton { private static Singleton instancja; protected Singleton()

Singleton (Singleton) Przykładowy kod C#: class Singleton { private static Singleton instancja; protected Singleton() {}; //ukryty konstruktor public static Singleton Instancja { get { if (instancja == null) //lazy initialization instancja = new Singleton(); return instancja; } } };

Singleton (Singleton) Przykładowy kod C# (w wielu wątkach): class Singleton { private static lock.

Singleton (Singleton) Przykładowy kod C# (w wielu wątkach): class Singleton { private static lock. Object = typeof(Singleton); private static Singleton instancja; protected Singleton() {}; //ukryty konstruktor public static Singleton Instancja { get { lock(lock. Object) { if (instancja == null) //lazy initialization instancja = new Singleton(); return instancja; }

Singleton (Singleton) Problemy: Wzorzec krytykowany za - odmiana zmiennych globalnych - kontrolę tworzenia i

Singleton (Singleton) Problemy: Wzorzec krytykowany za - odmiana zmiennych globalnych - kontrolę tworzenia i cyklu życia - powoduje „ciasne” wiązania w kodzie Singleton vs dziedziczenie Zadanie domowe (1) i konkursy (2): 1. Zmodyfikować wzorzec Singletonu w taki sposób, aby możliwe było tworzenie N instancji 2. Znaleźć sposób, aby uniemożliwić niezależne tworzenie klas potomnych (C#: modyfikator sealed)

Prototyp (Prototype) • Założenia: Fabryka, która kopiuje przechowywane wzorcowe instancje produktów, czyli prototypy •

Prototyp (Prototype) • Założenia: Fabryka, która kopiuje przechowywane wzorcowe instancje produktów, czyli prototypy • Konsekwencje: 1. Produkty muszą mieć możliwość klonowania (konstruktor copy i/lub metoda Clone) 2. Inicjowanie stanu klonów już po ich utworzeniu (a więc nie przez konstruktor!) 3. Można zmieniać produkt w trakcie działania programu (wystarczy podmienić prototyp)

Prototyp (Prototype) • Implementacja: Stworzymy alternatywną fabrykę abstrakcyjną, przechowującą prototypy i zwracającą ich kopie

Prototyp (Prototype) • Implementacja: Stworzymy alternatywną fabrykę abstrakcyjną, przechowującą prototypy i zwracającą ich kopie na żądanie • Nazwy używane w kontekście tego wzorca: Miejsce. WLabiryncie – Prototype, prototyp (deklaruje metodę Klonuj) Komórka, Ściana, Drzwi – Concrete prototype, produkt konkretny (definiują metodę Klonuj) Fabryka. Labiryntu. ZPrototypami – Client (przechowuje instancje prototypów i je klonuje)

Prototyp (Prototype) http: //zenit. senecac. on. ca/wiki/index. php/Prototype

Prototyp (Prototype) http: //zenit. senecac. on. ca/wiki/index. php/Prototype

Prototyp (Prototype) Zadanie domowe (1) i konkurs (2): 1. Rozszerzyć fabrykę o prototyp labiryntu

Prototyp (Prototype) Zadanie domowe (1) i konkurs (2): 1. Rozszerzyć fabrykę o prototyp labiryntu 2. Zmienić kod fabryki tak, żeby przechowywała dowolną tablicę prototypów

Wzorce konstrukcyjne - zadania 1. Poprzez refaktoryzację doprowadź projekt 'Wąż' do architektury MVC. 2.

Wzorce konstrukcyjne - zadania 1. Poprzez refaktoryzację doprowadź projekt 'Wąż' do architektury MVC. 2. W aplikacji Windows Forms lub WPF zdefiniować metodę wytwórczą, która będzie tworzyła przycisk, umieszczała go w zadanym miejscu formy lub panelu i zmieniała jego kolor na podany w argumencie. Kliknięcie przycisku powinno powodować zmianę koloru przycisku na czarny. Zdefiniuj metodę wytwórczą, która buduje zielono-czerwoną szachownicę o podanym w argumencie rozmiarze, w której klikanie przycisków powoduje zmianę ich koloru na czarny. Stwórz fabrykę abstrakcyjną, która buduje szachownicę. Kolory będą podane w fabryce konkretnej. Zmień fabrykę w fabrykę z prototypami, w której wzorzec przycisku (bez koloru) podawany jest przez argument konstruktora. 3. 4. 5.

Wzorce strukturalne Wzorce dotyczące relacji między klasami, rozwiązujące typowe problemy systemów z wieloma klasami:

Wzorce strukturalne Wzorce dotyczące relacji między klasami, rozwiązujące typowe problemy systemów z wieloma klasami: • • Adapter (Adapter) • Most (Bridge) Dekorator (Decorator) • Pełnomocnik (Proxy) Fasada (Facade) • Pyłek (Flyweight) Kompozyt (Composite)

Adapter (Adapter) Założenia (adapter klasowy): Client używa obiektów pochodnych względem Target. Chcemy użyć także

Adapter (Adapter) Założenia (adapter klasowy): Client używa obiektów pochodnych względem Target. Chcemy użyć także Adaptee, ale ma inny interfejs. Tworzymy Adapter typu Target (relacja jest), który korzysta z obiektu Adaptee (wielodziedziczenie). http: //zenit. senecac. on. ca/wiki/index. php/Adapter http: //www. frederikprijck. net/external-libraries-and-the-adapter-pattern/

Adapter (Adapter) • Implementacja Nowy kod: funkcja WIo. F(Wielokąt. Foremny*) Istniejący kod: klasa Prostokąt

Adapter (Adapter) • Implementacja Nowy kod: funkcja WIo. F(Wielokąt. Foremny*) Istniejący kod: klasa Prostokąt Chcemy użyć nowej funkcji dla istniejącej klasy. W. NET: interfejs określający wymagania klienta (ITarget) • Nazwy używane w kontekście tego wzorca: Wielokąt. Foremny – Target, element docelowy Wyświetl. Informacje. OFigurze – Client Prostokąt – Adaptee, klasa dostosowywana Prostokąt. Foremny – Adapter, kl. dostosowująca

Adapter (Adapter) • Adapter klasowy i adapter obiektowy – Adapter obiektowy nie adaptuje klasy

Adapter (Adapter) • Adapter klasowy i adapter obiektowy – Adapter obiektowy nie adaptuje klasy (dziedziczeniem prywatnym), a obiekt tej klasy przekazywany przez argument konstruktora – Adapter klasowy nie działa dla klas potomnych Adaptee, a obiektowy – tak – Adapter klasowy może przesłaniać funkcje Adaptee, w adapterze obiektowym to jest trudne • Adapter dwukierunkowy (przezroczystość) • Adaptery dołączalne – umieją dynamicznie, na podstawie dostarczonych danych, pobierać dane z Adaptee, którego typ nie jest ustalony przy kompilacji

Dekorator (Decorator) Założenia: Chcemy dodać funkcjonalność/obowiązek do jednego obiektu, bez zmieniania jego klasy. Włożymy

Dekorator (Decorator) Założenia: Chcemy dodać funkcjonalność/obowiązek do jednego obiektu, bez zmieniania jego klasy. Włożymy go w lekką otoczkę, która doda funkcję. http: //zenit. senecac. on. ca/wiki/index. php/Adapter

Dekorator (Decorator) • Implementacja Dekorator to klasa dziedzicząca z Component (interfejs) i mająca Component

Dekorator (Decorator) • Implementacja Dekorator to klasa dziedzicząca z Component (interfejs) i mająca Component jako pole (na przechowanie Concrete component). Udostępnia metody i pola tego pola modyfikując je lub dodając. • Nazwy używane w kontekście tego wzorca: Napój – Component Herbata, Kawa – Concrete component Napój. ZDodatkiem – Decorator Napój. ZPlastrem. Cytryny – Concrete decorator

Fasada (Facade) Założenia: Dodatkowa klasa udostępniająca metody wyższego poziomu złożone z wielu wywołań metod

Fasada (Facade) Założenia: Dodatkowa klasa udostępniająca metody wyższego poziomu złożone z wielu wywołań metod biblioteki lub podsystemu klas. Tworzy ujednolicony prosty interfejs. http: //www. tonymarston. net/php-mysql/design-patterns. html#facade (na podstawie rysunku z G 4)

Fasada (Facade) • Przykład: Realizowanie zamówień: 1. Sprawdzenie dostępności towaru 2. Wypełnienie formularza 3.

Fasada (Facade) • Przykład: Realizowanie zamówień: 1. Sprawdzenie dostępności towaru 2. Wypełnienie formularza 3. Zapłacenie rachunku 4. Dostarczenie Fasada: Złóż zamówienie • Nazwy używane w kontekście tego wzorca: Napoje. Menu – Facade Herbata, Napój. ZCytryną, itd. - klasy podsystemu

Kompozyt (Composite) Cel: Pozwala na budowanie z obiektów struktury drzewa (hierarchia część-całość) http: //zenit.

Kompozyt (Composite) Cel: Pozwala na budowanie z obiektów struktury drzewa (hierarchia część-całość) http: //zenit. senecac. on. ca/wiki/index. php/Composite

Kompozyt (Composite) • Przykład: • Nazwy używane w kontekście tego wzorca: IPracownik – Component

Kompozyt (Composite) • Przykład: • Nazwy używane w kontekście tego wzorca: IPracownik – Component Pracownik – Leaf Kierownik – Composite funkcja main – Client

Kompozyt (Composite) Zalety: • Nadrzędny element (korzeń drzewa) reprezentuje wszystkie elementy podrzędne (uproszczenie interfejsu,

Kompozyt (Composite) Zalety: • Nadrzędny element (korzeń drzewa) reprezentuje wszystkie elementy podrzędne (uproszczenie interfejsu, a więc i kodu klienta) • Można definiować wiele liści (np. klasy potomne po Pracownik) i wiele kompozytów (np. klasy potomne po kierownik) – możliwość rozszerzania zbioru klas Kompozyty z cyklami: Zwykle kompozyt kojarzymy z drzewami, ale może zawierać cykle – należy to uwzględnić przy korzystaniu z rozwiązań bazujących na rekurencjach.

Kompozyt (Composite) Zadanie domowe: Zadeklarować w interfejsie IPracownik i zaimplementować w klasie Pracownik metodę

Kompozyt (Composite) Zadanie domowe: Zadeklarować w interfejsie IPracownik i zaimplementować w klasie Pracownik metodę Count zliczającą liczbę elementów w podstukturze. Uwzględnić możliwość istnienia cykli w strukturze kompozytu (gdy pracownik staje się np. dziekanem).

Kompozyt (Composite) Konkursy: 1. Zmodyfikować kod w taki sposób, aby metoda Wyświetl. Informacje lepiej

Kompozyt (Composite) Konkursy: 1. Zmodyfikować kod w taki sposób, aby metoda Wyświetl. Informacje lepiej pokazywała strukturę obiektów (drzewo). Jak przekazać stopień zagnieżdżenia? 2. Zaimplementować w klasie Kierownik interfejs IEnumerable<IPracownik>, który umożliwia umożliwić pobranie iteratora (IEnumerator) pozwalającego na przeglądanie całej struktury podwładnych (w dowolnym poziomie zagnieżdżenia). Uwzględnić ewent. obecność cykli.

Most (Bridge) Cel: Rozdziela interfejs od implementacji, także dziedziczenia (bogate uchwyty do klas –

Most (Bridge) Cel: Rozdziela interfejs od implementacji, także dziedziczenia (bogate uchwyty do klas – handle/body class) http: //en. wikipedia. org/wiki/Bridge_pattern

Most (Bridge) Założenia: • Skrzyżowanie dwóch lub więcej katerogii (np. klasy różnego typu implementowane

Most (Bridge) Założenia: • Skrzyżowanie dwóch lub więcej katerogii (np. klasy różnego typu implementowane dla różnych platform) powoduje „zoo” klas i zależności. • Jeżeli oddzielimy i ukryjemy implementacje, to podział samym „interfejsów” klas jest prostszy. • Most to nazwa dla relacji między abstrakcją (ogólnym interfejsem) a abstrakcyjną implementacją • Dobry przykład: figury rysowane w różnych systemach graficznych (podział figur vs API do ich rysowania) • Nasz przykład: relacja pilot-telewizor(y)

Most (Bridge) • Przykład: http: //www. informit. com/articles/article. aspx? p=1398603&seq. Num=4 • Nazwy używane

Most (Bridge) • Przykład: http: //www. informit. com/articles/article. aspx? p=1398603&seq. Num=4 • Nazwy używane w kontekście tego wzorca: Shape – Abstraction Rectangle, Circle – Refined Abstraction Drawing – Implementor Win. Drawing, XDrawing – Concrete Implementor

Pełnomocnik (Proxy) Cel: „Cieńki” pełnomocnik „grubej” klasy (inny kontekst niż most) http: //www. slideshare.

Pełnomocnik (Proxy) Cel: „Cieńki” pełnomocnik „grubej” klasy (inny kontekst niż most) http: //www. slideshare. net/pickerweng/android-camera-architecture-8098156 (na bazie G 4)

Pełnomocnik (Proxy) Cel: „Cieńki” pełnomocnik „grubej” klasy (inny kontekst niż most) http: //www. slideshare.

Pełnomocnik (Proxy) Cel: „Cieńki” pełnomocnik „grubej” klasy (inny kontekst niż most) http: //www. slideshare. net/pickerweng/android-camera-architecture-8098156 (na bazie G 4)

Pełnomocnik (Proxy) • Przykład: https: //sourcemaking. com/design_patterns/proxy • Nazwy używane w kontekście tego wzorca:

Pełnomocnik (Proxy) • Przykład: https: //sourcemaking. com/design_patterns/proxy • Nazwy używane w kontekście tego wzorca: Środki. Płatności - Subject Czek. Bankowy – Proxy Gotówka, Pieniądze. WBanku – Real Subject

Pełnomocnik (Proxy) Założenia: • Pełnomocnik wirtualny - odraczanie kosztów związanych z ewentualnym tworzeniem „grubego”

Pełnomocnik (Proxy) Założenia: • Pełnomocnik wirtualny - odraczanie kosztów związanych z ewentualnym tworzeniem „grubego” obiektu (por. leniwa inicjacja) • Zdalny pełnomocnik obiektu z innego procesu lub komp. • Pośrednik zabezpieczający – celem jest zabezpieczenie obiektu lub programu (sprawdzanie blokad), a nie ograniczenie użycia zasobów • Inteligentne wskaźniki (referencje) – realizują także powyższe cele • Pośrednik danych – częsty przykład, unifikacja

Pełnomocnik (Proxy) Leniwa inicjacja class Math. Proxy : public IMath { private: Math* math;

Pełnomocnik (Proxy) Leniwa inicjacja class Math. Proxy : public IMath { private: Math* math; Math* get. Math. Instance() { if (!math) math = new Math(); return math; } public: Math. Proxy() : math(NULL) {}

Pyłek (Flyweight) Cel: Zmniejszyć zużycie pamięci zmarnowanej na obsługę wielu powielonych obiektów (por. prosta

Pyłek (Flyweight) Cel: Zmniejszyć zużycie pamięci zmarnowanej na obsługę wielu powielonych obiektów (por. prosta kompresja) http: //flylib. com/books/en/2. 505. 1. 19/1/ (na bazie G 4)

Pyłek (Flyweight) Warunki stosowania: • Aplikacja korzysta z dużej liczby powtarzających się obiektów •

Pyłek (Flyweight) Warunki stosowania: • Aplikacja korzysta z dużej liczby powtarzających się obiektów • Koszty przechowywania tych obiektów są duże • Stan obiektu można zapisać poza nim • Nie ma porównywania obiektów Porównaj z najprostszą metodą kompresji przez kodowanie słownikowe (LZ/Lempel-Ziv, ZIP, RAR, PNG), słownik statyczny (określony przez klasy pyłków)

Pyłek (Flyweight) • Przykład: http: //flylib. com/books/en/2. 505. 1. 19/1/ (na bazie G 4)

Pyłek (Flyweight) • Przykład: http: //flylib. com/books/en/2. 505. 1. 19/1/ (na bazie G 4) • Nazwy używane w kontekście tego wzorca: Znak – Flyweight Znak. A, Znak. B, . . . – Concrete. Flyweight Fabryka. Znaków – Flyweight. Factory main, document – Client

Wzorce operacyjne Wzorce dotyczące dzielenia odpowiedzialności między współpracującymi ze sobą obiektami (porządkują złożone przepływy

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)

Interpreter (Interpreter) Cel: Stworzenie mini-języka używanego w programie http: //zenit. senecac. on. ca/wiki/index. php/Interpreter

Interpreter (Interpreter) Cel: Stworzenie mini-języka używanego w programie http: //zenit. senecac. on. ca/wiki/index. php/Interpreter

Interpreter (Interpreter) Implementacja: Tworzona jest klasa główna reprezentująca cały interpreter oraz klasy potomne reprezentujące

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ł

Interpreter (Interpreter) • Przykład: liczby w notacji rzymskiej liczba. Rzymska : : = {tysiące}

Interpreter (Interpreter) • Przykład: liczby w notacji rzymskiej liczba. Rzymska : : = {tysiące} {setki} {dziesiątki} {jedności} tysiące, setki, dziesiątki, jedności : : = dziewięć | cztery | {pięć} {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: Interpreter. Liczb. Rzymskich – wyrażenie abst. Interpreter. Tysięcy, . . . – wyrażenie pośrednie liczby. Rzymskie – Context (informacje globalne) main – Client

Iterator (Iterator) Cel: Umożliwia sekwencyjny dostęp do elementów agregatu bez konieczności eksponowania wewnętrznej struktury.

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

Iterator (Iterator) Standardowe metody iteratora: template <typename Element> class Iterator { public: virtual void

Iterator (Iterator) Standardowe metody iteratora: template <typename Element> class Iterator { public: virtual void First() = 0; virtual void Next() = 0; virtual bool Is. Done() = 0; virtual Element Current. Element() = 0; protected: Iterator(){} }; Ukryty konstruktor – metoda wytwórcza w agregatorze

Iterator (Iterator) Implementacja z rozdzieleniem iteratora i agregatu: http: //zenit. senecac. on. ca/wiki/index. php/Iterator

Iterator (Iterator) Implementacja z rozdzieleniem iteratora i agregatu: http: //zenit. senecac. on. ca/wiki/index. php/Iterator

Iterator (Iterator) • Przykład: Abstrakcyjny. Stos, Iterator - abstrakcje Stos – prosta implementacja z

Iterator (Iterator) • Przykład: Abstrakcyjny. Stos, Iterator - abstrakcje Stos – prosta implementacja z tablicą do przechow. Stos. Iterator – pozwala na przebiegnięcie wszystkich zapamiętanych elementów (wbrew naturze stosu) • Nazwy używane w kontekście tego wzorca: Iterator – Iterator. Stos. Iterator – Concrete. Iterator Abstrakcyjny. Stos – Aggregate Stos – Concrete. Aggregate

Iterator (Iterator) • W platformie. NET jest interfejs IEnumerable<T>, który kontaktuje metodę Get. Enumerator

Iterator (Iterator) • W platformie. NET jest interfejs IEnumerable<T>, który kontaktuje metodę Get. Enumerator zwracającą iterator implementujący interfejs IEnumerator<T>. • Interfejs IEnumerator<T> deklaruje: własność Current zwracającą bieżący elment typu T, metodę Move. Next 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

Iterator (Iterator) Dostęp do kolekcji. NET z wielu wątków: Problemem pojawia się jeżeli iterator

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)

Iterator (Iterator) Iterator dla kompozytu: 4. Tworzenie płytkiej kopii kolekcji i iteracja po niej

Iterator (Iterator) Iterator dla kompozytu: 4. Tworzenie płytkiej kopii kolekcji i iteracja po niej (por. 2)

Iterator (Iterator) Zadania domowe: 1. Niech klasa Kierownik (wzorzec kompozyt) implementuje int. IEnumerable<IPracownik> pozwalający

Iterator (Iterator) Zadania domowe: 1. Niech klasa Kierownik (wzorzec kompozyt) implementuje int. IEnumerable<IPracownik> 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.

Łańcuch zobowiązań (Chain of Responsibility) Cel: Osłabienie wiązania klienta zgłaszającego żądanie (request), czyli wywołania

Ł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

Łańcuch zobowiązań (Chain of Responsibility) Implementacja: Implementacja podobna do kolejki (ale może być np.

Ł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 Win. API. 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

Łańcuch zobowiązań (Chain of Responsibility) • Wada: Nie ma gwarancji obsłużenia żądania (wśród obiektów

Ł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 wie, czy żądanie zostanie obsłużone żądanie, czy w ogóle lub ile razy • Nazwy używane w kontekście tego wzorca: Handler. Bazowy – Handler, obiekt obsługujący, Handler 1, . . – Concrete. Handler, obiekt obsługujący main – Client

Mediator (Mediator) Cel: Zmniejszyć liczbę powiązań między równorzędnymi elementami systemu (podgrupami). Typowe: GUI, redukcja

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

Mediator (Mediator) Cel: Mediator może także pełnić rolę strażnika integralności stanów obiektów zdefiniowanych w

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

Mediator (Mediator) • Przykład: Klasyczna implementacja listy, w której każdy element przechowuje wskaźnik do

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 Concrete. Mediator

Metoda szablonowa (Template Method) Cel: Implementacja rodziny algorytmów różniących się szczegółami (np. przygotowywanie pizzy:

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)

Metoda szablonowa (Template Method) Przygotowywanie pizzy – dwa przykładowe przepisy: (na podstawie referatu Łukasza

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

Metoda szablonowa (Template Method) Uwagi: • Ciekawe źródło: http: //www. objectmentor. com/resources/ articles/inheritance. Vs.

Metoda szablonowa (Template Method) Uwagi: • Ciekawe źródło: http: //www. objectmentor. com/resources/ articles/inheritance. Vs. Delegation • 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)

Metoda szablonowa (Template Method) • Nazwy używane w kontekście tego wzorca: Pizza – Abstract.

Metoda szablonowa (Template Method) • Nazwy używane w kontekście tego wzorca: Pizza – Abstract. Class, zawiera metodę szablonową Margherita, Sycylijska – Concrete. Class main – Client

Obserwator (Observer) Cel: Rozluźnienie wiązania między zależnymi od siebie klasami (dwiema lub wieloma) przez

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

Obserwator (Observer) • Typowy przykład: model widoku i reagujące na zmiany jego stanu widoki

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 INotify. Property. Changed i INotify. Collection. Changed z platformy. NET (WPF) i platformy Win. RT • Nazwy używane w kontekście tego wzorca: Model – Subject, interfejs podmiotu lub sam podmiot Model 1, Model 2 – Concrete. Subject (niekonieczne) Widok – Observer, interfejs obserw. z met. Aktualizuj Widok. Tabela, Widok. Wykres – Concrete. Observer

Obserwator (Observer) • Zdarzenia jako implementacja wzorca obserwator: button. Click += new Event. Handler(o.

Obserwator (Observer) • Zdarzenia jako implementacja wzorca obserwator: button. Click += new Event. Handler(o. metoda) button – instancja obserwabli, źródło danych Event. Handler – 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

Obserwator (Observer) • Reactive Extensions (Rx) - biblioteka ułatwiająca programowanie asynchroniczne i oparte na

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<T>, IObserver<T>, ISubject<T> • 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)

Odwiedzający (Visitor) Cel: Załóżmy strukturę obiektów, np. kompozyt pracowników. Na każdym pracowniku chcemy wykonać

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

Odwiedzający (Visitor) https: //sourcemaking. com/design_patterns/visitor

Odwiedzający (Visitor) https: //sourcemaking. com/design_patterns/visitor

Odwiedzający (Visitor) • Przykład: wydrukujemy informacje o pracownikach z drzewa (kompozytu) • Nazwy używane

Odwiedzający (Visitor) • Przykład: wydrukujemy informacje o pracownikach z drzewa (kompozytu) • Nazwy używane w kontekście tego wzorca: IPracownik – Element Pracownik, Kierownik – Concrete. Element Odwiedzający – Visitor Odwiedzajacy. Zliczający – Concrete. Visitor rektor – Object. Structure

Odwiedzający (Visitor) Zalety/Wady: Po zaimplementowaniu wzorca Odwiedzający możemy swobodnie dodawać kolejne czynności realizowane na

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,

Pamiątka (Memeno) Inna nazwa: Znacznik (Token) Cel: Zapis wewnętrznego stanu innego obiektu (źródła) bez

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

Pamiątka (Memento) • Przykład: punkty kontrolne (cofnij/ponów), przechowywanie stanu w aplikacjach mobilnych • Nazwy

Pamiątka (Memento) • 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ątka. Licznika – Memento, pamiątka main – zarządca (np. mechanizm cofania)

Pamiątka (Memento) • Przykład: wstrzymywanie i wznawianie działania aplik. • Trwała pamiątka: zapis stanu

Pamiątka (Memento) • 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

Polecenie (Command) Inna nazwa: Akcja (Action), Transakcja (Transaction) Cel: zamyka żądanie/funkcję/metodę w formie obiektu,

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

Polecenie (Command) Realizacja: przechowywanie wskaźnika do funkcji/metody opcja 1: może także przechowywać parametry wywołania

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 Relay. Command w MVVM http: //zenit. senecac. on. ca/wiki/index. php/Command

Pamiątka / Polecenie Zadanie domowe: W aplikacji Notatnik przygotować system Undo/Redo Cofanie (un-do) powinno

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.

Stan (State) Idea: Skomplikowana funkcjonalność klasy, zależna od parametrów (tj. od aktualnego stanu instancji

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/pat 5 hfso. htm (na podstawie Go. F)

Stan (State) Realizacja: Klasa główna przechowuje adresy klas reprezentujących poszczególne stany i deleguje na

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 (Go. F), Drzwi (Stan = Drzwi. Zamknięte, Drzwi. Otwarte) Nazwy używane w kontekście tego wzorca: Drzwi – Context, klasa udostępniana klientom Stan. Drzwi – State, stan – interfejs do kapsułkowania zachowania klasy Drzwi w różnych stanach Drzwi. Zamkniete , Drzwi. Otwarte – poszczeg. stany main – klient

Strategia (Strategy) Idea: rodzina algorytmów, każdy reprezentowany przez osobną klasę, które mogą być używane

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

Strategia (Strategy) Realizacja: Klasa główna przechowuje adres klasy reprezentującej wybrany algorytm i korzysta z

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

Strategia (Strategy) Nazwy używane w kontekście tego wzorca: Odgadywacz. Liczby – Context, klasa udostępniana

Strategia (Strategy) Nazwy używane w kontekście tego wzorca: Odgadywacz. Liczby – Context, klasa udostępniana Strategia. Zgadywania. Liczby – Strategy, wspólny interfejs dla wielu konkretnych strategii (używanych do realizacji metody Odgadywacz. Liczby: : Zgaduj) Strategia. Po. Kolei, Strategia. Losowo – implementacje poszczególnych algorytmów main – klient

Wzorce spoza książki G 4 • Wzorzec strukturalny Private Class Data https: //sourcemaking. com/design_patterns/private_class_data

Wzorce spoza książki G 4 • 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

Rozkład MVC na proste wzorce • Aktywny model / widok – Użytkownik obserwator (widok

Rozkład MVC na proste wzorce • Aktywny model / widok – Użytkownik obserwator (widok obserwuje model) używa jest oglądany • Widok / kontroler – Kontroler Widok strategia (widok pozostawia obsługę modyfikuje aktualizuje reakcji kontrolerowi) Model • Widok – kompozyt (praca z zagnieżdżonymi widokami)

Inny podział wzorców Wzorce interfejsów: Adapter, Fasada, Kompozyt, Most Wzorce odpowiedzialności: Singleton, Obserwator, Mediator,

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