= Gang of Four (podle 4 autorů knihy, kde tyto návrhy představili) Hezky popsáno zde: https://refactoring.guru/design-patterns

  • 23 návrhových vzorů ve 3 kategoriích
  • nejsou to zákony, spíše ulehčení a doporučení při psaní a navrhování SW

1) Creational Patterns

  • mechanismy vytváření objektů tak, aby byly vhodné pro danou situaci
Singleton
  • využití: jazykové nastavení, konfigurace, databázové spojení
  • anti-pattern: emuluje globální proměnnou
    • proč je to nahovno? špatně se to testuje - singleton se velmi špatně testuje
    • co když mám více databází? více konfigurací?
      • to částečně řeší multiton
  • v začátcích se hodí, poté už ne, vyplatí se ho už neuvažovat
Factory
  • místo toho, aby Client vytvářel článek, tak požádá Factory, aby mu ho vytvořila
    • a k tomu článek “zabalím” do Interface, takže s ním můžu pracovat jako s obecným článkem
    • tím pádem mohu mít Article a Comment tvořený různými Factory, ale tyto dva objekty sdílí jeden Interface
  • factory vytváří jeden jediný interface, ale ten může implementovat více objektů, které jsou tvořeny jednotlivými implementacemi té factory
Abstract Factory
  • umožňuje vytvářet více příbuzných či závislých objektů bez znalosti implementace jejich konkrétních tříd
    • konkrétní implementace je pak dána použitou továrnou
Builder
  • je řízen Director třídou - řídí strukturu výsledného produktu
    • Director ví pořadí operací, Builder ví implementaci konkrétních operací
  • Builder umí postavit jednotlivé části produktu
  • hodí se pro vytváření komplexních objektů
  • třída, která něco sestavuje
  • udělám si implementaci menších částí a pak je mohu spojovat a třeba řetězit za sebe
  • mohu složitější objekty sestavovat za běhu aplikace
Prototyp
  • kopírování existujících objektů
  • není nutné ruční sestavování (třeba mám i nedostupné private properties)
    • nebo znám jenom interface k tomu objektu atd.
    • hlavně, když kopíruju takhle objekt ručním kopírováním, stávám se závislým na tom objektu a to nechci
  • většinou implementován metodou clone() - tedy deleguji proces klonování na ten samotný objekt

2) Structural Patterns

  • uspořádání tříd či komponent aplikace
  • lepší přehlednost
Proxy
  • poskytuje alternativní přístup k objektu (pro lazy-loading (načtení celého objektu, až když ho opravdu potřebuji), caching)
  • video do paměti nenahraju
    • např. se dotazuju jenom na metadata k videu
    • ProxyVideo má pak odkaz na skutečný objekt s videem - nemusím ho loadovat dokud nemusím
    • implementuji třídu, která má stejný interface jako ta původní
      • a mohu měnit chování před a po volání nějakých metod (stejně jako funguje Proxy)
Adapter
  • propojuje různé třídy s různým rozhraním (dodržení kompatibility mezi dvěma rozhraními)
  • konvertuje rozhraní jedné třídy na rozhraní druhé třídy
Bridge
  • oddělení abstrakce od implementace, aby se mohly vyvíjet samostatně
  • abstrakce se zajímá např. o to, jaké GUI komponenty se budou používat, ale o konkrétní implementaci se nezajímá - to pak řeší ona “propojená” část - to se pak dá vyvíjet samostatně a často měnit
  • propojuje abstraktní části s jejich různými implementacemi, tedy veškerou logiku propojování mám na jednom místě
Facade
  • zjednodušuje rozhraní a sdružuje více metod a objektů, aby klienti byli izolováni od složitosti komponent
  • klienti pak nepotřebují znát, jak to přesně funguje “under the hood”
  • např. mám metodu createOrder(), která ve skutečnosti vezme věci z košíku, spočítá je, nacení, uplatní slevy, zavolá platební bránu, vypíše shrnutí objednávky, vygeneruje PDFko, pošle e-mail apod.
Composite
  • je možné skládat objekty do stromové struktury a pak s touto strukturou pracovat jako s jedním objektem
  • př. adresáře, skupiny, menu
  • př. objednávka v sobě má položky a balíčky položek (ve kterých mohou být položky i menší balíčky položek)
    • celkový objekt mi může dávat celkovou cenu položek, počet položek apod.
Decorator
  • obohacuje funkcionality objektů aniž by měnil jejich skutečnou implementaci
  • obalí je do jiiných objektů s přidanou funkcionalitou
    • tímhle způsobem mohu kombinovat více funkcionalit dohromady na základě preferencí uživatele (aniž bych v kódu měl vytvořené všechny možné kombinace - to by bylo neúnosné)
  • hodně se používají v Pythonu
Flyweight
  • podobný jako multiton
  • nezabývá se vytvářením objektů
  • instance sdílí stejné vlastnosti - šetření pamětí
    • na stránce mám 100x stejné tlačítko, akorát s jiným textem
    • šetření RAM tím, že se sdílí stejné vlastnosti mezi objekty
  • např. mám Tree() se souřadnicemi X,Y a zbytek vlastností je v TreeType() - např. název, barva, textura apod. a to sdílí všechny stromy stejného typu

3) Behavioral Patterns

  • zaměření na komunikaci mezi objekty, jak spolu interagují a jak jsou rozděleny zodpovědnosti
State
  • odděluje chování třídy závislé na stavu od samotné třídy (v závislosti na stavu třídy se mění její chování)
  • odstraňuje složitá větvení - switch, case, if else
  • stav není přístupný zvnějšku
    • objekt si drží informaci o stavu a sám si jej upravuje (existují přechody mezi stavy)
Observer
  • nevolejte nás, zavoláme vás
  • pozorující objekty (observers) se zaregistrují u pozorovaného objektu (observable)
  • pozorující objekt musí implementovat požadované rozhraní
  • při změně pozorovaného objektu pozorovaný objekt upozorní všechny jeho zaregistrované pozorující objekty, které na to pak mohou reagovat
  • jsou to vlastně Subscribery
Command
  • akci zapouzdří jako objekt, je možné ho volat kdykoliv
  • všechny informace pro tu akci zapouzdří v jednom objektu
  • podporuje i “undo” - tedy informace o opačném příkazu
    • můžeme akce dávat jako parametry, dávat je do fronty, či je zpožďovat
Visitor
  • přidává novou funkcionalitu do hierarchie tříd bez úpravy původních
  • přidá operaci, která se má vykonat na elementech struktury, ale nemění třídy elementů
  • je to výhodné pro návrh a analýzu, kdy chci provádět různé operace a zároveň nechci “znečišťovat” původní kód
  • v podstatě je to nová třída, která má metody, do kterých pošleme původní objekty, na kterých jsme chtěli dělat úpravy, provede je v rámci té metody a vrátí výsledek
Template method
  • definuje kostru algoritmu v methodě a části kroků deleguje do podtříd/podmetod
  • používá se, když nějaké algoritmy mají společnou strukturu a odlišnosti v detailech
    • ty odlišnosti pak implementují jednotlivé podtřídy
    • ale většina společného kódu bude v tom rodičovi
Strategy
  • objekt definuje konkrétní algoritmus a pro více algoritmů existuje rozhraní, díky kterému se dají jednoduše měnit
    • když je potřeba mít více různých typů algoritmů a dynamicky je měnit v runtime
Chain of responsibility
  • umožňuje předávat požadavek přes řetězec zpracovatelů, když jeden objekt nedokáže/nechce zpracovat požadavek, předá ho dál v řetězci
  • je to vhodné, když máme více zpracovatelů požadavku a dopředu nevíme, který ho bude zpracovávat
  • př. Autorizace/Autentizace, cache, logování…
Mediator
  • organizuje interakce mezi objekty (zprostředkovává komunikaci mezi nimi)
    • tím redukuje vzájemnou závislost těchto objektů (nejsou závislé na sobě přímo, ale přes Mediatora)
  • př. presenter, controller
Interpreter
  • reprezentace virtuálního jazyka (v rámci nějaké vlastní gramatiky)
  • používá se pro časté interpretace malých jazyků nebo jednoduchých skriptů
  • např. markdown interpreter, BBcode, definice hodnocení v nějakém známkovacím systému