Programovßnφ, podobn∞ jako v∞tÜina lidsk²ch Φinnostφ, mß svß "hesla dne". Kdo se jimi dostateΦn∞ Φasto nezaklφnß, nenφ "in", nem∙₧e b²t pova₧ovßn za odbornφka. V sedmdesßt²ch letech minulΘho stoletφ to bylo strukturovanΘ programovßnφ, p°ed deseti lety to bylo objektov∞ orientovanΘ programovßnφ, dnes to jsou mimo jinΘ nßvrhovΘ vzory.
To ale neznamenß, ₧e jde jen o prßzdnß m≤dnφ slova: mnohß z t∞chto hesel majφ hlubok² obsah a za masivnφm marketingem a propagandou tΘm∞° bolÜevickΘho ra₧enφ se mohou skr²vat - i kdy₧ se to Φlov∞ku obΦas nechce v∞°it - velice u₧iteΦnΘ v∞ci. To platφ i o nßvrhov²ch vzorech.
O co jde
Co to vlastn∞ ty nßvrhovΘ vzory, anglicky design patterns, vlastn∞ jsou?
Odpov∞∩ je pom∞rn∞ jednoduchß: Jde o popisy °eÜenφ nejb∞₧n∞jÜφch problΘm∙, s nimi₧ se v²vojß°i p°i nßvrhu softwaru setkßvajφ. Je jasnΘ, ₧e pro to, aby se urΦit² postup stal nßvrhov²m vzorem, nestaΦφ, aby poskytoval sprßvnΘ °eÜenφ pro jednu situaci. ╪eÜenφ musφ b²t pou₧itelnΘ pro celou t°φdu podobn²ch situacφ. Musφ ovÜem takΘ jφt o °eÜenφ, kterΘ se ukazuje jako nejv²hodn∞jÜφ z hlediska p°enositelnosti, rozÜi°itelnosti, udr₧ovatelnosti a °ady dalÜφch po₧adavk∙, kterΘ se na vyvφjen² software obvykle kladou (ale ne v₧dy se pak dodr₧ujφ).
Pokud vßm to znφ pov∞dom∞, nedivte se. Ono ve skuteΦnosti nejde o nic novΘho: svß ustßlenß °eÜenφ, tedy svΘ nßvrhovΘ vzory, mß v∞tÜina obor∙ tv∙rΦφ lidskΘ Φinnosti, architekturou poΦφnaje a psanφm romßn∙ nebo televiznφch serißl∙ konΦe.
NßvrhovΘ vzory pro tvorbu program∙ jsou zalo₧eny na objektov∞ orientovanΘm p°φstupu, i kdy₧ realizace °ady z nich v konkrΘtnφm programovacφm jazyce objektovß u₧ b²t nemusφ. V∞tÜina nßvrhov²ch vzor∙ nemß ₧ßdnΘho konkrΘtnφho autora, vznikla postupn²m, v podstat∞ darwinovsk²m v²vojem mezi programßtory, Φasto na mnoha mφstech zßrove≥.
Pom∞rn∞ dlouhou dobu ovÜem trvalo, ne₧ si lidΘ uv∞domili jejich existenci, a p°edevÜφm jejich cenu. I kdy₧ programßtorskß profese existuje u₧ od poΦßtku padesßt²ch let minulΘho stoletφ, teprve na poΦßtku devadesßt²ch let se nad nßvrhov²mi vzory vß₧n∞ zamyslela Φtve°ice ÜpiΦkov²ch programßtor∙ a softwarov²ch architekt∙ (Erich Gamma, Richard Helm, Ralph Johnson a John Vlissides), posbφrala nejb∞₧n∞jÜφ z nich, ut°φdila je a v roce 1995 o nich vydala knihu s prost²m nßzvem Design Patterns [1].
Trvalo ovÜem jeÜt∞ n∞jakou dobu, ne₧ programßto°i zaΦali v²znam nßvrhov²ch vzor∙ pln∞ doce≥ovat. V b∞₧n²ch uΦebnicφch programovßnφ se o nich zaΦalo hovo°it vlastn∞ a₧ na samΘm konci devadesßt²ch let; v souΦasnΘ dob∞ se znalost zßkladnφch nßvrhov²ch vzor∙ a schopnost jejich rozpoznßnφ stßvß jednφm z po₧adavk∙, kter² softwarovΘ firmy kladou na uchazeΦe o p°ijetφ na mφsto programßtora.
Poznamenejme, ₧e kniha [1] vyklßdß zßkladnφ nßvrhovΘ vzory pomocφ jazyka C++, obΦas takΘ pomocφ Smalltalku. Od tΘ doby se ve sv∞tovΘ literatu°e objevila °ada dalÜφch knih o nßvrhov²ch vzorech zalo₧en²ch na jin²ch jazycφch (nap°. na Jav∞), v∞tÜinou jde ovÜem o p°evyprßv∞nφ [1]. Pokud mohu posoudit, nedosahujφ ani zdaleka kvality p∙vodnφ publikace (i kdy₧ m∙₧e jφt o d∙sledek skuteΦnosti, ₧e mezi programovacφmi jazyky dßvßm p°ednost prßv∞ C++).
P°φklad
N∞kdy pot°ebujeme, aby jistß t°φda - °ekn∞me t°φda X - m∞la pouze jedinou instanci. I kdy₧ to mo₧nß na prvnφ pohled vypadß podivn∞, nejde o nic v²jimeΦnΘho. M∙₧e jφt nap°. o t°φdu p°edstavujφcφ souborov² systΘm v operaΦnφm systΘmu nebo o t°φdu p°edstavujφcφ °adiΦ tiskov²ch ·loh (spooler) v lokßlnφ poΦφtaΦovΘ sφti. Ve skuteΦnosti jde o natolik Φastou situaci, ₧e pro ni stßlo za to vytvo°it samostatn² nßvrhov² vzor, oznaΦovan² jako jedinßΦek neboli singleton.
Druhy nßvrhov²ch vzor∙
Auto°i knihy [1] rozd∞lili nßvrhovΘ vzory do t°φ zßkladnφch skupin a toto rozd∞lenφ dodr₧uje i v∞tÜina dalÜφch autor∙, kte°φ o nßvrhov²ch vzorech pφÜφ.
Prvnφ skupina obsahuje tvo°ivΘ (kreacionßlnφ) nßvrhovΘ vzory. To jsou vzory, kterΘ popisujφ r∙znΘ zp∙soby vytvß°enφ instancφ objektov²ch typ∙. Pomßhajφ zkonstruovat systΘm, kter² je nezßvisl² na podrobnostech zp∙sobu vytvß°enφ a sklßdanφ objekt∙, kterΘ ho tvo°φ.
Druhou skupinu tvo°φ strukturßlnφ nßvrhovΘ vzory, kterΘ se zab²vajφ zp∙soby sestavovßnφ t°φd nebo jednotliv²ch objekt∙ do slo₧it∞jÜφch struktur.
Poslednφ skupinu tvo°φ nßvrhovΘ vzory chovßnφ (behaviorßlnφ vzory). Ty se, struΦn∞ °eΦeno, zab²vajφ algoritmy a rozd∞lenφm ·kol∙ mezi jednotlivΘ objekty. Krom∞ samotn²ch objekt∙ nebo t°φd popisujφ takΘ zp∙soby komunikace mezi nimi, °φdicφ procesy, kterΘ se zde uplat≥ujφ, atd.
Tvo°ivΘ vzory
U₧ jsme si °ekli, ₧e jde o nßvrhovΘ vzory, kterΘ popisujφ zp∙soby vytvß°enφ objekt∙, tedy instancφ objektov²ch typ∙. Zapouzd°ujφ:
* informace o tom, jakΘ t°φdy systΘm pou₧φvß;
* informace o tom, jak se instance t∞chto t°φd vytvß°ejφ.
V²sledkem je, ₧e systΘm znß pouze rozhranφ objekt∙, s nimi₧ pracuje, a tφm zφskßvß nezßvislost na skuteΦnΘm typu pou₧it²ch objekt∙. Jednoduch²m p°φkladem tvo°ivΘho vzoru je u₧ zmφn∞n² jedinßΦek. Jin²m p°φkladem je abstraktnφ tovßrna (abstract factory); s jejφmi variantami se setkßme nap°. v automaticky generovanΘm k≤du p°i programovßnφ komponent COM. V objektov²ch knihovnßch se Φasto takΘ setkßme s tovßrnφ metodou.
Strukturßlnφ vzory
Tyto vzory popisujφ, jak vφme, varianty nßvrhu struktury t°φd. P°itom vyu₧φvajφ bu∩ sklßdßnφ objekt∙, nebo d∞diΦnost. Cφlem m∙₧e b²t:
* sklßdßnφ nebo zm∞na funkΦnosti (tedy implementace);
* sklßdßnφ nebo zm∞na rozhranφ objekt∙ nebo t°φd.
P°φkladem strukturßlnφho vzoru je adaptΘr. Tento nßvrhov² vzor umo₧≥uje p°izp∙sobit rozhranφ existujφcφ t°φdy po₧adavk∙m jejφho pou₧itφ. Jestli₧e mßme nap°. k dispozici t°φdu p°edstavujφcφ frontu a pot°ebujeme zßsobnφk, vytvo°φme zßsobnφk jako adaptΘr, kter² zapouzd°φ frontu do t°φdy s pot°ebn²m rozhranφm. Jin²m b∞₧n²m p°φkladem strukturßlnφho vzoru je most (bridge), v anglickΘ literatu°e takΘ oznaΦovan² jako the pimpl idiom. (Pimpl je zkratka slov pointer to implementation, tedy ukazatel na implementaci, a v podstat∞ vystihuje zp∙sob implementace.) Tento vzor umo₧≥uje od sebe odd∞lit rozhranφ a implementaci t°φdy tak, ₧e implementaci lze m∞nit i za b∞hu programu.
Poznamenejme, ₧e mnohΘ strukturßlnφ vzory jsou v r∙znΘ mφ°e p°φbuznΘ a za urΦit²ch situacφ je lze zam∞nit.
Vzory chovßnφ
Tyto nßvrhovΘ vzory se zab²vajφ algoritmy a rozd∞lenφm povinnostφ mezi objekty. Nepopisujφ jen skladbu objekt∙ Φi t°φd, ale takΘ zp∙soby komunikace mezi nimi. ╚asto charakterizujφ slo₧itΘ °φdicφ procesy, kterΘ je obtφ₧nΘ sledovat za b∞hu. Umo₧≥ujφ nßm mφsto procesu °φzenφ sledovat jen zp∙sob propojenφ mezi objekty.
Jednφm z nejΦast∞ji pou₧φvan²ch vzor∙ chovßnφ jsou iterßtory - objekty, na kterΘ se m∙₧eme dφvat jako na zobecn∞nφ ukazatel∙ na prvky polφ nebo jejich index∙. Umo₧≥ujφ pracovat stejn²m zp∙sobem s r∙zn²mi druhy kontejner∙, nejen s poli.
Jin²m Φasto pou₧φvan²m vzorem je pozorovatel (observer), oznaΦovan² takΘ jako vzor vydavatel-p°edplatitel (publisher-subscriber). Tento nßvrhov² vzor °eÜφ situaci, kdy r∙znΘ komponenty programu musφ reagovat na zm∞nu n∞kterΘho objektu. P°itom zpravidla nenφ znßmo, kterΘ komponenty a v jakou dobu to budou.
Pou₧itφ nßvrhov²ch vzor∙
I kdy₧ pou₧φvßnφ nßvrhov²ch vzor∙ nenφ zatφm mezi °adov²mi programßtory p°φliÜ rozÜφ°enΘ, tv∙rci knihoven a v²vojov²ch nßstroj∙ si ji₧ delÜφ dobu nemohou dovolit je pomφjet. To znamenß, ₧e s nßvrhov²mi vzory se ji₧ zcela b∞₧n∞ setkßvßme v r∙zn²ch objektov²ch knihovnßch a ve zdrojovΘm k≤du automaticky generovanΘm v²vojov²mi nßstroji.
Podφvejme se na n∞kolik namßtkou vybran²ch p°φklad∙:
* Standardnφ zp∙sob zpracovßnφ udßlostφ v Jav∞ je zalo₧en na nßvrhovΘm vzoru pozorovatel.
* Pro prßci se sekvenΦnφmi kontejnery se ve standardnφ ÜablonovΘ knihovn∞ C++ (STL), ale i v knihovnßch Javy nebo C#, pou₧φvajφ iterßtory.
* èablona zßsobnφku je v STL vytvo°ena jako adaptΘr vyu₧φvajφcφ vektor, seznam nebo dvoustrannou frontu.
* Instance t°φd automaticky generovan²ch v²vojov²mi prost°edφmi pro tvorbu aplikacφ CORBA nebo COM na zßklad∞ jazyka IDL jsou zpravidla vytvß°eny pomocφ abstraktnφch tovßren a implementace t∞chto t°φd je zalo₧ena na vzoru most.
Co z toho plyne?
Na nßvrhovΘ vzory se m∙₧eme dφvat jako na analogii matematick²ch, geometrick²ch, fyzikßlnφch a jin²ch vzoreΦk∙, kterΘ se uΦφme na zßkladnφ Ükole a kterΘ nßs pak provßzejφ po cel² ₧ivot. Chceme-li si spoΦφtat plochu koberce, proto₧e Φistφrna nep°ijφmß v∞tÜφ ne₧ 5 m2, zm∞°φme si jeho strany a pak pou₧ijeme vzorec pro v²poΦet plochy obdΘlnφka. Ten samoz°ejm∞ neodvozujeme, ten znßme, nebo¥ pat°φ k zßkladnφmu vzd∞lßnφ. NßvrhovΘ vzory v programovßnφ dnes zaΦφnajφ hrßt podobnou roli p°i tvorb∞ poΦφtaΦov²ch aplikacφ. Podrobn∞jÜφ Φlßnek o nßvrhov²ch vzorech najdete na Chip CD.
Miroslav Virius
Literatura:
[1] Erich Gamma, Richard Helm, Ralph Johnson a John Vlissides: Design Patterns. Addison-Wesley 1995. ╚esk² p°eklad Nßvrh program∙ podle vzor∙, Grada Publishing 2003. Na tuto knihu mnozφ auto°i odkazujφ znaΦkou GoF, co₧ je zkratka anglick²ch slov Gang of Four - parta Φty°.