Program přednášky
Co jsou návrhové vzory
Typy návrhových vzorů
Příklady konkrétních návrhových vzorů
Literatura a elektronické zdroje
Co jsou návrhové vzory
• Obecné řešení častého problému při návrhu
software
• Explicitně pojmenované obecné principy,
které programátoři intuitivně dávno znají
• Návrhové vzory × algoritmy × knihovny
Proč používat návrhové vzory
• Podporují správné programátorské postupy
• Podporují principy čistého OOP
• Nevymýšlíte již vymyšlené
• Rozšiřitelnost a znovupoužitenost aplikace
• Čitelnost aplikace, jednotná filozofie
Factory Method
instance se nezískává přes konstruktor,
ale nepřímo pomocí statické metody
metoda může vracet i již existující instanci
nejsme vázáni konkrétní třídou instance
v obecnějším pojetí deklaruje jen rozhraní,
konkrétní typy instance určují potomci
často využívána v rámci ostatních vzorů
Singleton
v aplikaci nejvýše jedna instance nějaké třídy
typicky instance aktuálního uživatele
například Zend_Auth, Zend_Registry,
Zend_Controller_Front, pooly, cache apod.
využívá Factory Method
konstruktor, klonování, serializovatelnost
z puristického hlediska není úplně čistý
Singleton: proč objekt a nikoliv třída
objekt může implementovat rozhraní
odkaz na něj se může předávat jako parametr
je možné i v průběhu aplikace rozhodnout,
které třídy bude vytvářený objekt instancí
pokud odpovídá nějakému objektu reálného
světa, je zpravidla vhodné jej instancovat
Library class
seskupené statické metody
nevytváří se instance, jen statické volání
mělo by se zabránit možnosti instancování
pokud je potřeba nějaká statická proměnná,
možná bude vhodnější použít singleton
například Zend_Json
Iterator
zajišťuje sekvenční přístup k nějakému
seznamu, kontejneru, poli apod.
zapouzdřuje vnitřní implementaci uložiště
v PHP (SPL) zabudovaný interface Iterator,
jeho implementace lze použít v cyklu foreach
správně by neměl být instancován přímo, ale
pomocí Factory method nad daným uložištěm
např. Zend_Config, Zend_Form apod.
Template Method
definuje základní kostru nějakého algoritmu
dílčí kroky mohou definovat až jednotliví
potomci pomocí překrytých metod
struktura algoritmu ale zůstává stejná
šablonová metoda je zpravidla finální
rodič je zpravidla abstraktní
Adapter
potřebuji, aby třída měla jiné rozhraní, než
má
mezi ni a sebe vložím adaptér, který převede
skutečné rozhraní na mnou požadované
sjednocení různých rozhraní do jednotného
požadované rozhraní dáno zpravidla nějakým
definovaným interface – tři možnosti
realizace
Decorator
Alternativa k dědění
Přidává k objektu další dodatečnou funkčnost
Původní objekt zabalí do jiného objektu
Vnější objekt zajišťuje nové funkce, vše
ostatní deleguje na původní objekt
Oba dva by měli mít společného rodiče
(abstraktní třída či interface)
Observer
Pozorovatelé se na začátku zaregistrují
u pozorovaného objektu
Při nějaké události pak pozorovaný objekt
upozorní všechny registrované pozorovatele
Typicky u událostmi řízeného programování
Registrace dynamicky anebo natvrdo v kódu
Literatura
Erich Gamma, Richard Helm, Ralph Johnson,
John Vlisside: Design Patterns: Elements of Reusable
Object-Oriented Software. Addison Wesley, 1995.
Erich Gamma, Richard Helm, Ralph Johnson,
John Vlisside: Návrh programů pomocí vzorů.
Stavební kameny objektově orientovaných
programů.
Grada, 2003.
Rudolf Pecinovský: Návrhové vzory
Computer press, 2007.
Elektronické zdroje
• Bruce Eckel: Thinking in patterns.
www.bruceeckel.com
• Wikipedia: en.wikipedia.org/wiki/Design_pattern
(computer_science)
• Vince Huston: www.vincehuston.org/dp/
• Miloš Dvořák: Návrhové vzory (design patterns)
objekty.vse.cz/Objekty/Vzory
• Pavel Drbal: objekty.vse.cz
• Ilja Kraval: www.objects.cz
instance se nezískává přes konstruktor, ale nepřímo pomocí statické metody – factory1.php metoda může vracet i již existující instanci – factory2.php nejsme vázáni konkrétní třídou instance – factory3.php v obecnějším pojetí deklaruje jen rozhraní, konkrétní typy instance určují potomci - často využívána v rámci ostatních vzorů, například singleton, (iterator), pool
lazy/late initialization – odložená (pozdní, líná) inicializace – až v getInstance early ( časná ) inicializace – již při deklaraci statické proměnné – private static $instance = new Foo; -- unexpected T_NEW serializovatelnost – unserialize je vedle konstruktoru a klonování další cesta, jak vznikají instance – byly by tam dvě singleton1.php – základní kostra singleton2.php – ukázka na Auth singleton3.php – totéž na statické třídě
- v SPL (Standard PHP Library) – Iterator, RecursiveIterator, RecursiveIteratorIterator, ArrayIterator, DirectoryIterator, CachingIterator apod. - iterator1.php – definice interface - iterator2.php –ukázka použití – instancování iterátoru „vedle“ uložiště – uložiště se klonuje apod. (rozhraní Iterable v Javě) – odděluje se tak samotné uložiště od svého iterátoru – na to je ale potřeba mít možnost soukromých vnitřních tříd, což PHP neumí
template1.php
adapter1.php - nebo samostatná třída implementující daný interface, která má instanci cílové třídy ve své proměnné – Zend_Auth_Adapter_Interface adapter2.php - buď obecný předek všech adaptérů s implicitníma metodama + jejich předefinování v konkrétních potomcích (nevýhoda – nutnost mít ho jako předka) -- např. abstract class Zend_Translate_Adapter_Abstract, Zend_Db_Adapter_Abstract - ale i tady by měl být k dispozici interface! a vše proti němu – u Zendu chybí adapter3.php - nebo potomek cílové třídy implementující daný interface – v Zendu není – ukázka s Nette
decorator1.php - prasopes
například reverzní kaskáda u kaskádové transparentní hierarchické cache