Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| statnice:bakalar:b6b36omo [2025/06/12 10:20] – [Behavioral design patterns] prokop | statnice:bakalar:b6b36omo [2025/06/13 07:31] (current) – [Structural design patterns: adapter, proxy, bridge, composite, facade, decorator, flyweight] prokop | ||
|---|---|---|---|
| Line 395: | Line 395: | ||
| </ | </ | ||
| - | {{statnice: | + | {{statnice: |
| === Builder === | === Builder === | ||
| Line 582: | Line 582: | ||
| {{statnice: | {{statnice: | ||
| + | |||
| + | === Composite Design Pattern === | ||
| + | |||
| + | * Účel: | ||
| + | * Umožňuje jednotné zacházení s **jednotlivými objekty** i s **jejich složením (stromová struktura)**. | ||
| + | * Používá se pro reprezentaci **hierarchických struktur** (např. souborový systém, GUI komponenty, organizace). | ||
| + | |||
| + | * Struktura: | ||
| + | * **Component** – společné rozhraní pro listy i složené objekty. | ||
| + | * **Leaf** – jednoduchý objekt (např. soubor). | ||
| + | * **Composite** – složený objekt (např. složka obsahující další objekty). | ||
| + | |||
| + | * Výhody: | ||
| + | * Rekurzivní zpracování hierarchických struktur. | ||
| + | * Klientský kód se nemusí starat, zda pracuje s listem nebo composite – volá jednotné metody. | ||
| + | * Umožňuje dynamicky přidávat/ | ||
| + | |||
| + | === Příklad použití: souborový systém === | ||
| + | |||
| + | <code java> | ||
| + | interface FileSystemItem { | ||
| + | void display(String indent); | ||
| + | } | ||
| + | |||
| + | class File implements FileSystemItem { | ||
| + | private String name; | ||
| + | |||
| + | public File(String name) { | ||
| + | this.name = name; | ||
| + | } | ||
| + | |||
| + | public void display(String indent) { | ||
| + | System.out.println(indent + "- File: " + name); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | class Folder implements FileSystemItem { | ||
| + | private String name; | ||
| + | private List< | ||
| + | |||
| + | public Folder(String name) { | ||
| + | this.name = name; | ||
| + | } | ||
| + | |||
| + | public void add(FileSystemItem item) { | ||
| + | children.add(item); | ||
| + | } | ||
| + | |||
| + | public void display(String indent) { | ||
| + | System.out.println(indent + "+ Folder: " + name); | ||
| + | for (FileSystemItem item : children) { | ||
| + | item.display(indent + " | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | public class CompositeDemo { | ||
| + | public static void main(String[] args) { | ||
| + | Folder root = new Folder(" | ||
| + | root.add(new File(" | ||
| + | |||
| + | Folder src = new Folder(" | ||
| + | src.add(new File(" | ||
| + | src.add(new File(" | ||
| + | |||
| + | root.add(src); | ||
| + | root.display("" | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| === Decorator === | === Decorator === | ||
| Line 888: | Line 958: | ||
| * Odděluje algoritmus od struktury dat. | * Odděluje algoritmus od struktury dat. | ||
| * Umožňuje přidat nové operace bez změny datové struktury. | * Umožňuje přidat nové operace bez změny datové struktury. | ||
| + | * Realizace patternu je pomocí tzv. **double dispatch** principu. | ||
| + | * Elementy datové struktury u kterých chci v budoucnosti přidávat operace, mají metodu accept(Visitor) uvnitř které zavolám na vloženém visitoru metodu visitElement(Element) | ||
| + | * Tím předám řízení visitoru a zároveň mu předám referenci | ||
| <code java> | <code java> | ||
| | | ||
| Line 1102: | Line 1175: | ||
| * Umožňuje vrátit objekt do předchozího stavu. | * Umožňuje vrátit objekt do předchozího stavu. | ||
| * Využívá se pro `undo`, `redo` funkce. | * Využívá se pro `undo`, `redo` funkce. | ||
| + | * Struktura: | ||
| + | * `Originator` – objekt, jehož stav se ukládá. | ||
| + | * `Memento` – objekt obsahující uložený stav. | ||
| + | * `Caretaker` – spravuje historii mement bez znalosti detailů. | ||
| + | |||
| <code java> | <code java> | ||
| - | | + | // Memento – reprezentuje uložený stav |
| - | | + | |
| - | | + | |
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Originator – třída s měnitelným stavem | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | state = memento.getState(); | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Caretaker – uchovává historii stavů | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Použití | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | originator.setState(" | ||
| + | | ||
| + | |||
| + | originator.setState(" | ||
| + | caretaker.add(originator.saveStateToMemento()); | ||
| + | |||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| </ | </ | ||
| {{: | {{: | ||
| === Interpreter === | === Interpreter === | ||
| - | * Vyhodnocuje výrazy v definovaném jazyce | + | * Definuje jazyk (syntaxi + sémantiku) pomocí tříd. |
| - | * Každý prvek jazyka | + | * Každý prvek výrazu |
| + | * Používá se k implementaci jednoduchých jazyků, výrazů, konfigurací, | ||
| + | * Struktura: | ||
| + | * `Expression` – rozhraní nebo abstraktní třída pro všechny výrazy. | ||
| + | * `TerminalExpression` – konkrétní výrazy (proměnné, | ||
| + | * `NonTerminalExpression` – operace (např. sčítání, | ||
| + | * `Context` – mapa proměnných (např. {" | ||
| <code java> | <code java> | ||
| - | | + | // Rozhraní pro výraz |
| - | new Variable(" | + | |
| - | | + | int interpret(Map< |
| - | | + | } |
| - | | + | |
| - | | + | // Terminální výraz – proměnná |
| - | | + | |
| - | | + | |
| - | | + | |
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Non-terminal – součet | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Non-terminal – rozdíl | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Ukázka použití | ||
| + | | ||
| + | | ||
| + | | ||
| + | new Variable(" | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | Map< | ||
| + | | ||
| + | |||
| + | | ||
| + | } | ||
| + | } | ||
| </ | </ | ||
| - | {{: | + | {{: |
| ===== Datové struktury a patterny: lazy loading, object pool, cache map, filter, reduce pattern ===== | ===== Datové struktury a patterny: lazy loading, object pool, cache map, filter, reduce pattern ===== | ||
| + | |||
| + | === Lazy Loading === | ||
| + | * Odložené načtení dat z paměti, databáze nebo vzdáleného zdroje. | ||
| + | * Zvyšuje efektivitu, pokud některá data nejsou vždy potřeba. | ||
| + | * Čtyři hlavní implementace: | ||
| + | * **Virtual Proxy** – místo objektu se vrací proxy, která objekt načte při prvním použití. | ||
| + | * **Lazy Initialization** – načítání na základě podmínky `if (obj == null)`. | ||
| + | * **Ghost** – objekt se načítá po částech podle potřeby (např. jen ID, pak detaily). | ||
| + | * **Value Holder** – objekt zabalený v obalu, který řídí načtení hodnoty. | ||
| + | |||
| + | <code java> | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | if (contacts == null) { | ||
| + | | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | if (realList == null) { | ||
| + | | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | {{statnice: | ||
| + | |||
| + | === Object Pool === | ||
| + | * Vzor, který opakovaně používá drahé objekty místo jejich opakovaného vytváření a likvidace. | ||
| + | * Typické použití: | ||
| + | * JDBC připojení (`ConnectionPool`) | ||
| + | * File handle | ||
| + | * HTTP klienti | ||
| + | * Pool může mít parametry: minimální/ | ||
| + | <code java> | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | pool = new ArrayBlockingQueue<> | ||
| + | for (int i = 0; i < maxSize; i++) { | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Použití: | ||
| + | | ||
| + | | ||
| + | // ... | ||
| + | | ||
| + | </ | ||
| + | |||
| + | | ||
| + | |||
| + | === Cache === | ||
| + | * Vzor, který ukládá data, která se často opakovaně používají. | ||
| + | * Používá se např. pro: | ||
| + | * Konfigurace, | ||
| + | * Základní princip: | ||
| + | * `get(key)` → pokud data nejsou nalezena, stáhnout z pomalého zdroje a uložit. | ||
| + | * Eviction policy (např. LRU) zabraňuje přetečení paměti. | ||
| + | |||
| + | <code java> | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | | ||
| + | if (!cache.containsKey(key)) { | ||
| + | if (cache.size() >= capacity) { | ||
| + | | ||
| + | | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Použití: | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | | ||
| + | |||
| + | === Map, Filter, Reduce (stream API) === | ||
| + | * Funkcionální operace na sekvencích dat (např. kolekce) umožňující čistý a efektivní styl programování. | ||
| + | * Vzniká **pipeline** z řetězených operací, které jsou **lazy** vyhodnocovány. | ||
| + | |||
| + | * **Map**: transformace každého prvku. | ||
| + | <code java> | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | * **Reduce**: agregace prvků do jedné hodnoty. | ||
| + | < | ||
| + | // Příklad z prezentace – nalezení největšího čísla | ||
| + | | ||
| + | |||
| + | int max = numbers.stream() | ||
| + | | ||
| + | |||
| + | | ||
| + | </ | ||
| + | |||
| + | * **Filter**: výběr pouze těch prvků, které splňují predikát. | ||
| + | < | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | * **Kombinování: | ||
| + | <code java> | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| ===== Specifikace, | ===== Specifikace, | ||
| + | |||
| + | < | ||
| + | ### Specifikace | ||
| + | |||
| + | = Formální popis toho, jak se má komponenta v systému chovat | ||
| + | |||
| + | - zahrnuje popis jejích rozhraní, funkcí a očekávaného chování | ||
| + | - představuje společný kontrakt pro implementátora komponenty a klienta komponenty | ||
| + | - význam specifikace: | ||
| + | |||
| + | |||
| + | **Behaviorální ekvivalence** | ||
| + | |||
| + | "Dva kódy jsou behaviorálně ekvivalentní, | ||
| + | |||
| + | - odpovídá na otázku zda-li se dva zdrojové kódy chovají stejně (možnost výměny kódu beze změny chování systému) | ||
| + | - není obecně testovatelná | ||
| + | - faktory ovlivňující behav. ekvivalenci: | ||
| + | - hraje roli i kontrakt mezi klientem a implementací: | ||
| + | - Preconditions = požadavky, které musí klient splnit, než zavolá funkci | ||
| + | - Postconditions = záruky, které funkce poskytne | ||
| + | |||
| + | **Změna specifikace** - silná vs. slabá | ||
| + | |||
| + | S2 je silnější nebo stejná jako S1 pokud: | ||
| + | - Preconditions pro S2 jsou slabší než nebo stejné jako pro S1 | ||
| + | - Postcondition pro S2 jsou silnější nebo stejné jako pro S1 | ||
| + | |||
| + | => můžeme nahradit S1 za S2 bez ovlivnění stávajících klientů | ||
| + | |||
| + | **Přesnost popisu specifikace** | ||
| + | - Deterministic: | ||
| + | - Undetermined: | ||
| + | |||
| + | Příklad: " | ||
| + | |||
| + | **Deklarativní vs Operativní specifikace** | ||
| + | |||
| + | - Deklarativní: | ||
| + | - Operativní: | ||
| + | |||
| + | (deklarativní preferovanější) | ||
| + | |||
| + | **Testování** - testy musí splňovat podmínky specifikace, | ||
| + | |||
| + | ### REST (Representational State Transfer) | ||
| + | |||
| + | = architektonický styl pro návrh webových API (nemusí být nutně vázaný na HTTP protokol) | ||
| + | - REST API jsou navrženy na základě resources = objekty/ | ||
| + | - každý resource má identifikátor - URI | ||
| + | - používá se jednotný interface, aby byl zajištěn decoupling klienta a serveru (v HTTP použito verb v hlavičce - get, put, post, delete, patch) | ||
| + | - ! je bezestavový, | ||
| + | |||
| + | Existují různé úrovně implementace: | ||
| + | - Level 0: jedno URI pro všechny operace, operace jsou post volání na toto URI | ||
| + | - Level 1: separátní URI pro jednotlivé resources | ||
| + | - Level 2: využití HTTP metod pro definici operací na resource | ||
| + | - Level 3: využití hypermedia odkazů (odpovědi obsahují URI na další resources např. objednávka -> uri pro položky) | ||
| + | |||
| + | **Web API** | ||
| + | |||
| + | = api na webovém serveru nebo klientu | ||
| + | - request response koncept, předávání zpráv ve formátu JSON nebo XML | ||
| + | - ve většine řešení postavený na HTTP (využívání response kódů) | ||
| + | |||
| + | SOAP (Simple Object Access Protocol) | ||
| + | |||
| + | - protokol pro komunikaci mezi 2 zařízeními | ||
| + | - pro popis služeb využívá WSDL (web services description language) - formální popis poskytované funkcionality (xml) | ||
| + | - zprávy jsou ve formátu XML | ||
| + | - zpřístupňuje klientovi funkce a operace (např. může mít funkci CreateEmployee pro vytvoření zaměstnance v systému) -> orientovaná procedurálně | ||
| + | - není cachovaný | ||
| + | - pomalejší | ||
| + | |||
| + | REST API | ||
| + | |||
| + | - zpřístupňuje klientovi data -> orientovaná datově | ||
| + | - využívá HTTP - metody pro přístup ke zdrojům: get, put, post, delete, patch | ||
| + | - podporuje různé formáty - především JSON ale mohou být různé | ||
| + | - popis endpointů je méně formální | ||
| + | - rychlejší | ||
| + | |||
| + | GraphQL | ||
| + | |||
| + | - efektivní nástupce REST API | ||
| + | - dává možnost specifikace požadovaných dat | ||
| + | - když operace vrací objektový graf, tak mohu specifikovat hloubku a podmnožiny atributů jednotlivých entit | ||
| + | - zvládá větší zátěž než REST | ||
| + | |||
| + | Open API | ||
| + | - Open API Initiative - zaměřuje se na vytvoření, | ||
| + | - Open API Specification | ||
| + | - definuje standard pro popis REST API, nezávislé na programovacím jazyku | ||
| + | - může být použita pro generování klientského i serverového kódu pro různé programovací jazyky, generování dokumentace, | ||
| + | |||
| + | Swagger | ||
| + | |||
| + | - framework pro definici rozhraní podle specifikace OpenAPI | ||
| + | - pokrývá celý životní cyklus REST API: | ||
| + | - návrh - Swagger Editor - nástroj pro psaní OpenAPI specifikace v YAML/JSON | ||
| + | - dokumentace - Swagger UI - vygeneruje interaktivní dokumentaci z OpenAPI popisu | ||
| + | - build - Swagger Codegen - automaticky generuje kód klientů/ | ||
| + | - testování - Swagger Inspector - umožňuje testovat API volání přímo z prohlížeče | ||
| + | - deployment - zakomponování do Docker apod. | ||
| + | |||
| + | na datové struktury se v rámci zpráv odkazuje pomocí REF - uri | ||
| + | |||
| + | APIARY | ||
| + | |||
| + | - obdobný nástroj swaggeru | ||
| + | |||
| + | </ | ||