Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
statnice:bakalar:b6b36omo [2025/06/12 10:20] – [Behavioral design patterns] prokopstatnice:bakalar:b6b36omo [2025/06/13 07:31] (current) – [Structural design patterns: adapter, proxy, bridge, composite, facade, decorator, flyweight] prokop
Line 395: Line 395:
 </code> </code>
  
-{{statnice:bakalar:omofprototype.png?700}}+{{statnice:bakalar:omoprototype.png?700}}
  
 === Builder === === Builder ===
Line 582: Line 582:
  
 {{statnice:bakalar:sinfacade.png?500}} {{statnice:bakalar:sinfacade.png?500}}
 +
 +=== 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/odebírat prvky.
 +
 +=== 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<FileSystemItem> children = new ArrayList<>();
 +
 +    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");
 +        root.add(new File("readme.txt"));
 +
 +        Folder src = new Folder("src");
 +        src.add(new File("Main.java"));
 +        src.add(new File("Utils.java"));
 +
 +        root.add(src);
 +        root.display("");
 +    }
 +  }
 +</code>
  
 === 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>
    public interface ComputerPart {    public interface ComputerPart {
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>
-   caretaker.saveState(originator.createMemento()); +   // Memento – reprezentuje uložený stav 
-   originator.setState("nový stav"); +   public class Memento { 
-   originator.restore(caretaker.getLastSavedState());+       private final String state; 
 + 
 +       public Memento(String state) { 
 +           this.state = state; 
 +       } 
 + 
 +       public String getState() { 
 +           return state; 
 +       } 
 +   } 
 + 
 +   // Originator – třída s měnitelným stavem 
 +   public class Originator { 
 +       private String state; 
 + 
 +       public void setState(String state) { 
 +           this.state = state; 
 +           System.out.println("Current state: " + state); 
 +       } 
 + 
 +       public Memento saveStateToMemento() { 
 +           return new Memento(state); 
 +       } 
 + 
 +       public void getStateFromMemento(Memento memento) { 
 +           state = memento.getState(); 
 +           System.out.println("State restored to: " + state); 
 +       } 
 +   } 
 + 
 +   // Caretaker – uchovává historii stavů 
 +   public class Caretaker { 
 +       private List<Memento> mementoList = new ArrayList<>(); 
 + 
 +       public void add(Memento state) { 
 +           mementoList.add(state); 
 +       } 
 + 
 +       public Memento get(int index) { 
 +           return mementoList.get(index); 
 +       } 
 +   } 
 + 
 +   // Použití 
 +   public class MementoDemo { 
 +       public static void main(String[] args) { 
 +           Originator originator = new Originator(); 
 +           Caretaker caretaker = new Caretaker(); 
 + 
 +           originator.setState("State #1"); 
 +           originator.setState("State #2"); 
 +           caretaker.add(originator.saveStateToMemento()); 
 + 
 +           originator.setState("State #3"); 
 +           caretaker.add(originator.saveStateToMemento()); 
 + 
 +           originator.setState("State #4"); 
 + 
 +           originator.getStateFromMemento(caretaker.get(0)); // State #2 
 +           originator.getStateFromMemento(caretaker.get(1)); // State #3 
 +       } 
 +   }
 </code> </code>
 {{:statnice:bakalar:omomemento.png?700}} {{:statnice:bakalar:omomemento.png?700}}
  
 === Interpreter === === Interpreter ===
-  * Vyhodnocuje výrazy v definovaném jazyce (např. matematický jazyk)+  * Definuje jazyk (syntaxi + sémantiku) pomocí tříd
-  * Každý prvek jazyka má vlastní třídu.+  * Každý prvek výrazu má svou třídu. 
 +  * Používá se k implementaci jednoduchých jazyků, výrazů, konfigurací, pravidel. 
 +  * Struktura: 
 +    * `Expression` – rozhraní nebo abstraktní třída pro všechny výrazy. 
 +    * `TerminalExpression` – konkrétní výrazy (proměnné, konstanty). 
 +    * `NonTerminalExpression` – operace (např. sčítání, odečítání). 
 +    * `Context` – mapa proměnných (např. {"x" → 10})
 <code java> <code java>
-   Expression exp new Plus( +   // Rozhraní pro výraz 
-       new Variable("w"), +   public interface Expression 
-       new Minus( +       int interpret(Map<String, Integer> context); 
-           new Variable("x"), +   } 
-           new Variable("z"+ 
-       +   // Terminální výraz – proměnná 
-   ); +   public class Variable implements Expression { 
-   Map<String, Integer> context = Map.of("w", 6, "x", 30, "z", 8); +       private String name; 
-   int result = exp.evaluate(context);  // výsledek: 6 + (30 8)+ 
 +       public Variable(String name) { 
 +           this.name name; 
 +       } 
 + 
 +       public int interpret(Map<String, Integer> context) { 
 +           return context.get(name); 
 +       } 
 +   } 
 + 
 +   // Non-terminal – součet 
 +   public class Plus implements Expression { 
 +       private Expression left, right; 
 + 
 +       public Plus(Expression left, Expression right) { 
 +           this.left = left; 
 +           this.right = right; 
 +       
 + 
 +       public int interpret(Map<String, Integer> context) { 
 +           return left.interpret(context) + right.interpret(context); 
 +       } 
 +   } 
 + 
 +   // Non-terminal – rozdíl 
 +   public class Minus implements Expression { 
 +       private Expression left, right; 
 + 
 +       public Minus(Expression left, Expression right) { 
 +           this.left = left; 
 +           this.right = right; 
 +       } 
 + 
 +       public int interpret(Map<String, Integer> context) { 
 +           return left.interpret(context) - right.interpret(context); 
 +       } 
 +   } 
 + 
 +   // Ukázka použití 
 +   public class InterpreterDemo { 
 +       public static void main(String[] args) { 
 +           Expression expr = new Plus( 
 +               new Variable("x"), 
 +               new Minus( 
 +                   new Variable("y"), 
 +                   new Variable("z"
 +               
 +           ); 
 + 
 +           Map<String, Integer> context = Map.of("x", 5, "y", 10, "z", 3); 
 +           int result = expr.interpret(context); // + (10 3= 12 
 + 
 +           System.out.println("Výsledek: " + result); 
 +       } 
 +   }
 </code> </code>
-{{:statnice:bakalar:omointerpreter.png?700}}+{{:statnice:bakalar:omointerpreter.png?500}}
  
 ===== 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>
 +   public class Company {
 +       private ContactList contacts;
 +
 +       public ContactList getContacts() {
 +           if (contacts == null) {
 +               contacts = new ContactListProxy(); // virtual proxy
 +           }
 +           return contacts;
 +       }
 +   }
 +
 +   public class ContactListProxy implements ContactList {
 +       private ContactList realList;
 +
 +       public List<Customer> getCustomers() {
 +           if (realList == null) {
 +               realList = new RealContactList(); // expensive operation
 +           }
 +           return realList.getCustomers();
 +       }
 +   }
 +</code>
 +
 +{{statnice:bakalar:omolazy.png?300}}
 +
 +=== 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í/ maximální počet instancí, TTL, idle cleanup.
 +<code java>
 +   public class ObjectPool<T> {
 +       private BlockingQueue<T> pool;
 +
 +       public ObjectPool(Supplier<T> creator, int maxSize) {
 +           pool = new ArrayBlockingQueue<>(maxSize);
 +           for (int i = 0; i < maxSize; i++) {
 +               pool.offer(creator.get());
 +           }
 +       }
 +
 +       public T borrow() throws InterruptedException {
 +           return pool.take();
 +       }
 +
 +       public void release(T obj) {
 +           pool.offer(obj);
 +       }
 +   }
 +
 +   // Použití:
 +   ObjectPool<Connection> connectionPool = new ObjectPool<>(MyConnection::new, 5);
 +   Connection conn = connectionPool.borrow();
 +   // ...
 +   connectionPool.release(conn);
 + </code>
 +
 + {{statnice:bakalar:omoobjpool.png?300}}{{statnice:bakalar:omoobjpool2.png?300}}
 +
 +=== Cache ===
 +* Vzor, který ukládá data, která se často opakovaně používají.
 +  * Používá se např. pro:
 +    * Konfigurace, katalogy, uživatelská data
 +  * 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>
 +   public class SimpleCache<K, V> {
 +       private final int capacity;
 +       private final Map<K, V> cache = new LinkedHashMap<>();
 +
 +       public SimpleCache(int capacity) {
 +           this.capacity = capacity;
 +       }
 +
 +       public synchronized V get(K key, Supplier<V> dataLoader) {
 +           if (!cache.containsKey(key)) {
 +               if (cache.size() >= capacity) {
 +                   Iterator<K> it = cache.keySet().iterator();
 +                   it.next(); it.remove(); // remove oldest
 +               }
 +               cache.put(key, dataLoader.get());
 +           }
 +           return cache.get(key);
 +       }
 +   }
 +
 +   // Použití:
 +   SimpleCache<String, Person> personCache = new SimpleCache<>(100);
 +   Person p = personCache.get("123", () -> loadPersonFromDB("123"));
 +</code>
 + {{statnice:bakalar:omocache.png?400}}
 +
 +=== 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>
 +     List<String> names = people.stream()
 +         .map(Person::getName)
 +         .collect(Collectors.toList());
 +  </code>
 +
 +  * **Reduce**: agregace prvků do jedné hodnoty.
 +   <code java>
 +     // Příklad z prezentace – nalezení největšího čísla
 +     List<Integer> numbers = Arrays.asList(5, 12, 3, 21, 7);
 +
 +     int max = numbers.stream()
 +         .reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b); \\tady passujeme lambda funkci
 +
 +     System.out.println("Maximum: " + max);
 +   </code>
 +
 +  * **Filter**: výběr pouze těch prvků, které splňují predikát.
 +   <code java>
 +     List<Person> fromPraha = people.stream()
 +         .filter(p -> p.getCity().equals("Praha"))
 +         .collect(Collectors.toList());
 +   </code>
 +
 +  * **Kombinování:**
 +  <code java>
 +     List<String> sortedNames = people.stream()
 +         .filter(p -> p.getCity().equals("Praha"))
 +         .map(Person::getName)
 +         .sorted()
 +         .collect(Collectors.toList());
 +  </code>
 +
  
 ===== Specifikace, návrhy specifikací, web API, Apiary, Swagger, GraphQL ===== ===== Specifikace, návrhy specifikací, web API, Apiary, Swagger, GraphQL =====
 +
 +<markdown>
 +### 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: předchází chybám, srozumitelnost, připravenost na změny
 +
 +
 +**Behaviorální ekvivalence**
 +
 +"Dva kódy jsou behaviorálně ekvivalentní, pokud při stejných vstupech ve stejném kontextu dávají stejné výstupy a vedou ke stejnému stavu systému."
 +
 + - 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: Vstupní hodnoty, Kontext běhu, Vedlejší efekty, Chybové stavy
 + - 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: jednoznačně určený výstup
 +- Undetermined: není jednozačně určen výstup 
 +
 +Příklad: "vrátí __první__ index i, kde arr[i] = val" vs "vrátí index i, kde arr[i] = val"
 +
 +**Deklarativní vs Operativní specifikace**
 +
 +- Deklarativní: nepopisuje detaily interních kroků implementace, popisuje výstup na základě vstupů
 +- Operativní: popisuje kroky implementace, slouží jako návod pro vývojáře
 +
 +(deklarativní preferovanější)
 +
 +**Testování** - testy musí splňovat podmínky specifikace, testy nesmí být podřízeny implementaci, ale výhradně specifikaci rozhraní
 +
 +### 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/data/služby ke kterým klient přistupuje
 +- 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ý, odpovědi mohou být cacheovány
 +
 +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í,zkvalitňování a propagaci formátu pro popis rozhraní, které bude nezávislé na dodavateli
 +- 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, validace obsahu zpráv, testování
 +
 +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ů/serverů podle specifikace
 +  - 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
 +
 +</markdown>
Navigation

Playground

QR Code
QR Code statnice:bakalar:b6b36omo (generated for current page)