23
Využijte sílu jazyka C# při řešení programátorských problémů Judith Bishopová C# návrhové vzory

C# - návrhové vzory

Embed Size (px)

DESCRIPTION

Využijte sílu jazyka C# při řešení programátorských problémů

Citation preview

Page 1: C# - návrhové vzory

Využijte sílu jazyka C# při řešení programátorských problémů

Judith Bishopová

C#návrhovévzory

Page 2: C# - návrhové vzory
Page 3: C# - návrhové vzory

C#

Judith Bishopová

návrhové vzory

Page 4: C# - návrhové vzory

C# 3.0 Design PatternsJudith Bishop

© ZONER soft ware, a.s., 2010. Authorized translation of the English edition of C# 3.0 Design Patterns © 2007 O'Reilly Media Inc. Th is translation is published and sold by permission of O'Reilly Media Inc., the owner of all rights to publish and sell the same. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, inclu-ding photocopying, recording or by any information storage retrieval system, without permission from O'Reilly Media Inc.

© ZONER soft ware, a.s., 2010. Autorizovaný překlad originálního anglického vydání knihy C# 3.0 Design Patterns © 2007 O'Reilly Media Inc. Překlad je vydán a prodáván s výslovným svolením O'Reilly Media Inc., vlastníkem veškerých práv na vydání i prodej tohoto titulu. Žádná část této publikace nesmí být reprodukována nebo předávána žádnou formou nebo způsobem, elektronicky ani mechanicky, včetně fotokopií, natáčení ani žádnými jinými systémy pro ukládání bez výslovného svolení O'Reilly Media Inc.

C# – návrhové vzoryAutor: Judith Bishopová

Copyright © ZONER soft ware, a.s. Vydání první v roce 2010. Všechna práva vyhrazena.

Zoner PressKatalogové číslo: ZR805

ZONER soft ware, a.s.Nové sady 18, 602 00 Brno

Překlad: Jiří KoutnýOdborná korektura: Mgr. Martin Kruliš a Miroslav KučeraŠéfredaktor: Ing. Pavel KristiánDTP: Miroslav Kučera

Informace, které jsou v této knize zveřejněny, mohou byt chráněny jako patent. Jména produktů byla uvedena bez záruky jejich volného použití. Při tvorbě textů a vyobrazení bylo sice postupováno s maximální péčí, ale přesto nelze zcela vyloučit možnost výskytu chyb. Vydavatelé a autoři nepřebírají právní odpovědnost ani žádnou jinou záruku za použití chybných údajů a z toho vyplývajících důsledků. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována ani dis-tribuována žádným způsobem ani prostředkem, ani reprodukována v databázi či na jiném záznamovém prostředku či v jiném systému bez výslovného svolení vydavatele, s výjimkou zveřejnění krátkých částí textu pro potřeby recenzí.

Veškeré dotazy týkající se distribuce směřujte na:

Zoner Press ZONER soft ware, a.s. Nové sady 18, 602 00 Brno

tel.: 532 190 883, fax: 543 257 245 e-mail: [email protected] www.zonerpress.cz

ISBN 978-80-7413-076-2

Page 5: C# - návrhové vzory

Vzpomínkám na mého milovaného tatínka, Toma Mullinse (1920–2007)

Page 6: C# - návrhové vzory

4

Obsah Předmluva 7

Úvod 9

Poděkování 13

Kapitola 1 C# s návrhovými vzory 15

O vzorech 16

O UML 17

Jazyk C# 3.0 19

O příkladech 20

Kapitola 2 Strukturální vzory: Decorator, Proxy a Bridge 21

Vzor Decorator (Dekorátor) 22

Vzor Proxy 36

Vzor Bridge (Most) 51

Srovnání jednotlivých vzorů 62

Kapitola 3 Strukturální vzory: Composite a Flyweight 65

Vzor Composite (Kompozit) 65

Vzor Flyweight (Muší váha) 77

Porovnání vzorů 90

Kapitola 4 Strukturální vzory: Adapter a Faςade 91

Vzor Adapter (Adaptér) 91

Vzor Faςade (Fasáda) 111

Porovnání vzorů 118

Kapitola 5 Vytvářecí vzory: Prototype, Factory Method a Singleton 119

Vzor Prototype (Prototyp) 119

Vzor Factory Method (Tovární metoda) 129

Page 7: C# - návrhové vzory

5

Vzor Singleton (Jedináček) 133

Porovnání vzorů 139

Kapitola 6 Vytvářecí vzory: Abstract Factory a Builder 141

Vzor Abstract Factory (Abstraktní továrna) 141

Vzor Builder (Stavitel) 149

Porovnání vzorů 158

Kapitola 7 Vzory chování: Strategy, State a Template Method 159

Vzor Strategy (Strategie) 159

Vzor State (Stav) 169

Vzor Template Method (Šablonová metoda) 180

Porovnání vzorů 184

Kapitola 8 Vzory chování: Chain of Responsibility a Command 187

Vzor Chain of Responsibility (Zřetězení odpovědnosti) 187

Vzor Command (Příkaz) 199

Porovnání vzorů 211

Kapitola 9 Vzory chování: Iterator, Mediator a Observer 213

Vzor Iterator (Iterátor) 213

Vzor Mediator (Prostředník) 226

Vzor Observer (Pozorovatel) 236

Diskuse o vzorech a srovnání 244

Kapitola 10 Vzory chování: Visitor, Interpreter a Memento 247

Vzor Visitor (Návštěvník) 247

Vzor Interpreter (Interpret) 261

Vzor Memento 271

Porovnání vzorů 282

Page 8: C# - návrhové vzory

6

Kapitola 11 Budoucnost návrhových vzorů 283

Shrnutí vzorů 283

Co nás čeká v budoucnosti? 287

Závěrečné poznámky 288

Dodatek 289

Příklad vzoru Adapter – CoolBook 289

Příklad vzoru Prototype – Archiv fotografi í 294

Příklad vzoru Iterator – Rodokmen 299

Příklad vzoru Observer – Blogy 302

Teoretický příklad vzoru Visitor – Refl exe 307

Příklad vzoru Interpreter – Pravidla kurzu 309

Příklad vzoru Interpreter – Mirrors 314

Seznam použité literatury 319

Rejstřík 321

Page 9: C# - návrhové vzory

7

PředmluvaKdyž čelíte nějakému problému, který máte vyřešit, mezi informatiky se často používá základní strategie "rozděl a panuj", kterou lze popsat následovně:

Vytvoření modelu konkrétního problému jako množiny několika menších problémů.

Samostatné vyřešení každého dílčího problému.

Řešení daného problému se získá zkombinováním dílčích výsledků.

Redukce složitých problémů na úroveň nastavování stavů několika milionů bitů je to, co děláme neustále. Ale "rozděl a panuj" není jedinou možnou strategií. Lze také použít obecnější přístup:

Vytvoření modelu konkrétního problému jako speciálního případu obecnějšího problému.

Nějakým způsobem vyřešit obecný problém.

Přizpůsobit řešení obecného problému specifickému problému.

Návrhové vzory jsou pro ty, kteří mají raději obecnější přístup. Pokud se podíváte na příklady ze širokého spektra softwarových řešení, zjistíte, že ačkoliv detaily se mohou velmi lišit, je často za nimi podobná obecná struktura. (Vyhledávání souboru v adresářové struktuře je v určitém smyslu strukturálně velmi podobné vyhledávání v derivačním stromu.) Návrhové vzory formalizují obec-ná řešení běžných problémů.

Základní příkladem obecného přístupu je samozřejmě návrh a implementace samotných progra-movacích jazyků. Jak se nástroje pro řešení problémů neustále vyvíjejí, je těžší být obecnější než programovací jazyk (jako je například C#). Při návrhu programovacích jazyků (nebo nových verzí starších programovacích jazyků) přemýšlíme o běžných problémech, kterým opravdoví vývojáři čelí každý den a uvažujeme nad tím, jak vytvořit jazyk, který bude problémy řešit obecně, esteticky a účinným, široce aplikovatelným, způsobem.

Chceme vložit nejužitečnější a nejsilnější abstrakce do infrastruktury jazyka tak hluboko, že je sotva zaregistrujete, jako by tam vůbec nebyly. Vzory jako "lokální proměnná", "volání procedury" nebo "cyklus while" jsou natolik součástí vzduchu, který dýcháme, že už je ani nepovažujeme za vzory.

Navíc chceme udělat jazyk, ve kterém jsou vzory (které jsou sice užitečné, ale ne zas tak až moc důležité) relativně přímo, čistě a jasně implementovatelné. Třída v programovacím jazyku C# může být označena jako "static", "abstract" nebo "sealed", ale ne jako "singleton". To byla záměrná volba návrhářů jazyka, ačkoli implementace sigleton třídy v C# je relativně jednoduchá.

Šedá zóna mezi "nepostradatelným" a "příležitostně užitečným" je právě tím místem, kde leží zají-mavé výzvy návrhu. Pozorování návrhových vzorů, které používají vývojáři v C# (a také v dalších jazycích), silně ovlivňuje proces navrhování nových verzí. Zvažte například, jak byste například implementovali vzor Iterator pro lineární seznam (linked list) v C# 1.0. Skončili byste definová-ním třídy enumerátoru pro reprezentaci pozice v seznamu obsahujícím spoustu nudného a znovu omílaného kódu (což snižuje čitelnost), přičemž výsledné řešení by nebylo moc opakovatelně po-

Page 10: C# - návrhové vzory

8

užitelné. Protože pojem "výčet věcí" je snadno aplikovatelný na široké spektrum problémů, bývá zahrnut do mnoha jazyků. V C# 2.0 s příkazem yied return může pro vás kompilátor vygenerovat všechen ten nudný kód a systém generických typů bude iterovat přes kolekci věcí bez ohledu na to, co jsou tyto "věci" vlastně zač.

Tohle všechno je jen zdlouhavý způsob jak říct, proč jsem tak nadšený z LINQ (Language Inte-grated Query) v C# 3.0. Věřím, že iterace přes kolekce věcí je skvělý začátek, ale můžeme udělat mnohem víc. Třídění, filtrování, seskupování, spojování, projekce či transformace dat jsou další důležité operace, které jsou užitečné v každé oblasti. Ať už píšete kompilátor, čtečku XML nebo nějaký bezpečnostní systém pro internetové bankovnictví, je velká šance, že budete potřebovat mnoha způsoby manipulovat s kolekcemi.

Odstraněním těchto konceptů z doménově-specifických modelů objektů a jejich vložením přímo do programovacího jazyka pro obecné účely lze vyřešit všelijaké obecnější problémy. Doufám také, že přidání dotazovacích výrazů, lambda výrazů, rozšiřovacích metod, výrazů inicializátoru atd. do C# povede ke zjednodušení implementace všech možný užitečných vlastností.

A to je také důvod, proč jsem nadšen knihou C# – návrhové vzory, která se věnuje občas těžko pochopitelnému svět návrhových vzorů ve spojení s C#. Těším se na dobu, až uvidím, jak vývojáři používají tyto nástroje a jaké užitečné vzory budeme moci zabudovat do infrastruktur budoucích jazyků.

– Eric LippertSenior Developer

C# Compiler TeamSeattle, Washington

30. listopad, 2007

Page 11: C# - návrhové vzory

9

Úvod

Proč jsem napsala tuto knihuV roce 2002 Microsoft Research hostoval mezinárodní setkání v Cambridge ve Velké Británii, kde představil systém Rotor, který by přinesl C# a .NET i programátorům na jiných platformách, než je Windows. Jakmile jsem se vrátila domů a začala psát software, články a knihu na toto téma, uvědomila jsem si, že jsem byla svědkem opravdové revoluce v programování. Od příchodu Javy v roce 1996 bylo programování nezávislé na platformě: díky Java bytecode mohly programy běžet kdekoliv. Tato nezávislost nicméně rozšířila pouze programy, které byly napsány v Javě. Na druhou stranu – .NET je zcela nezávislý na jazyce, protože umožňuje interakci programů, které byly napsá-ny v různých jazycích, ale zatím jen na platformě Windows.

V následujících pěti letech podpořily technologii .NET nejenom nové platformy, jako je třeba Mono (http://www.mono-project.com), ale také nový hardware s podporou čipů od Intelu (na kterých běží Windows). Výsledkem toho všeho je, že .NET nyní běží téměř kdekoliv. S přihlédnu-tím k těmto faktům lze říci, že znalost jazyka C# je rozhodně přenositelná dovednost. C# se ale jako programovací jazyk neustále zlepšuje a v době psaní této knihy jsme byli svědky posunu směrem k verzi 3.0, která přinesla další zlepšení produktivity a zjednodušení programování. Uvědomila jsem si, že nově ohlášené vlastnosti budou znamenat mnohem pokročilejší úroveň vývoje softwaru a chtěla jsem napsat knihu, která by představila C# 3.0 vývojářům, kteří už mají za sebou nezbytné základy. Jenže jak postupovat, abych v knize mohla představit samotný jazyk a současně čtenářům demonstrovat příklady, které mají svůj základ v reálném světě?

A zde přicházejí na scénu návrhové vzory.

Návrhové vzory dohromady zapouzdřují osvědčené způsoby pro využívání všelijakých funkcí ja-zyka. Umožňují programovat na vyšší úrovni a propagují dobré programátorské praktiky. Kolem návrhových vzorů nicméně existuje jistý mýtus neskutečnosti, takže někdo může mít dojem, že se o nich spíše mluví, než aby se používaly v praxi. To jsem ale chtěla změnit, takže jsem vymyslela takové příklady návrhových vzorů, které jsou srozumitelné i běžným programátorům za použití toho nejlepšího programovacího jazyka pro ně – C#. Výsledkem mé práce je tato kniha.

Komu je tato kniha určenaPokud jste programátor, který miluje svůj kód, pro kterého má každý řádek jasný smysl a každý znak své přesné místo, je tato kniha pro vás. Pomůže vám s prací při vytváření správného, elegant-ního, rozšiřitelného a efektivního kódu. Pokud se soustředíte na kvalitu kódu, rozhodně potřebu-jete knihu jako C# – návrhové vzory. Znalost návrhových vzorů je rovněž velkým krokem kupředu pro ty, kteří se chtějí vypracovat z běžných programátorů na softwarové inženýry a architekty.

Při čtení této knihy získáte následující dovednosti:

Programování s návrhovými vzory.

Page 12: C# - návrhové vzory

10

Základy UML modelování pro reprezentaci vzorů.

Vybírání vzorů vhodných pro dané scénáře a srovnávání alternativních implementací.

Používání pokročilých jazykových vlastnosti C# 3.0 k efektivní a elegantní realizaci vzorů.

Ačkoli kniha C# – návrhové vzory není psána jako učebnice, může posloužit jako kurz návrhových vzorů nebo programování pro středně pokročilé. Všechny UML diagramy, errata a zdrojové kódy pro vzory popisované v této knize můžete najít na této stránce:

http://patterns.cs.up.ac.za/

Znalosti nutné pro práci s touto knihouTato kniha je určena pro programátory, kteří umí programovat v C# 1.0, a kteří by se rádi dozvě-děli více informací o nových vlastnostech tohoto jazyka. Spousta nových vlastností z jazyka C# 3.0 (stejně jako mnoho nových vlastností z C# 2.0) je představeno v příkladech. Tato kniha tudíž může posloužit i jako průvodce programátora světem C#.

Kniha od svých čtenářů nepředpokládá žádnou předchozí znalost návrhových vzorů. Pokrývá ce-lou sadu 23 vzorů, které původně navrhli Erich Gamma, Richard Helm, Ralph Johnson a John Vlisside v knize Design Patterns: Element sof Reusable Object-Oriented Software v roce 1994 a nyní formuje běžný základ do vzorů, které se objevují i v mnoha jiných oblastech (jako je bezpečnost, souběžnost či architektonický design). Po přečtení knihy by měl čtenář získat pevné základy o zde popisovaných vzorech.

Jak je tato kniha organizovánaPo nezbytném úvodu v kapitole 1 přichází 23 základních návrhových vzorů. Každá kapitola probírá dva nebo tři vzory podle toho, že mají podobné použití a mohou být na konci kapitoly vzájemně porovnány. Vzory jsou rozděleny do těchto tří skupin:

Strukturální vzory (kapitoly 2–4).

Vytvářecí vzory (kapitoly 5–6 ).

Vzory chování (kapitoly 7–10).

Začneme se strukturálními vzory. V kapitole 2 se budeme zabývat vzory Decorator, Proxy a Bridge. V kapitole 3 si popíšeme vzory Composite a Flyweight. V kapitole 4 vzory Adapter a Faςade. Poté se přesuneme k vytvářecím vzorům – v kapitole 5 objevíme vzory Prototype, Factory Method a Sing-leton. V kapitole 6 se zaměříme na vzory Abstract Factory a Builder. Poslední čtyři kapitoly se zabý-vají největší kategorií, což jsou vzory týkající se chování. Kapitola 7 se soustředí na vzory Strategy, State a Template Method. Kapitola 8 popisuje vzory Chain of Responsibility a Command. Kapitola 9 se zaměřuje vzory Iterator, Mediator a Observer. A konečně – poslední kapitola o vzorech se bude věnovat vzorům Visitor, Interpreter a Memento.

Page 13: C# - návrhové vzory

11C# – návrhové vzory

Naše diskuse o každém vzoru se bude skládat z následujících částí:

Účel. Krátký popis vzoru a toho, čeho by měl dosáhnout.

Ilustrace. Příklad toho, kde by vzor mohl být použit v moderních počítačových systémech ilustrující skutečný kontext s fotografií či diagramem, který pomůže si vzor zapamatovat.

Návrh. Popis účastníků vzoru a jejich účelu (vysvětleno v UML diagramu s odkazy zpět k ilustraci).

Implementace. Postupné vylepšování vývoje krátkého programu, který ilustruje vzor s pou-žitím pojmů zmíněných v oddíle Návrh.

Příklad. Druhý program, který ukazuje příklad vzoru, obvykle v pojmech ilustrativního pří-kladu, kde se programování odchyluje od přísného lpění na pojmech vzoru.

Použití. Popis skutečných scénářů, kde mohou být vzory použity. Tato sekce je zakončena seznamem podmínek, které by měly být splněny, aby mohl být vzor aplikován.

Cvičení. Seznam cvičení s různými úrovněmi obtížnosti, který je navržen tak, aby zvýšil vaše porozumění danému vzoru.

Na konci každé kapitoly pak naleznete porovnání vzorů, které v ní byly probrány a diskusi o tom, jak zapadají do těch vzoru, které už byly popsány.

Vzory byly pečlivě seřazeny tak, aby bylo možné reprezentovat jejich stupňující se vývoj z hlediska používání C# 3.0. Implementace dřívějších vzorů v každém oddíle obvykle vyžaduje trochu něče-ho, co není dostupné v C# 1.0, zatímco pozdější vzory mají sofistikovanější implementaci a výhodu v pokročilejších vlastnostech, které jsou dostupné v C# 3.0. Tento přístup umožňuje, aby mohla být daná vlastnost jazyka představena v okamžiku, jakmile se stane relevantním, což je mnohem praktičtější než tyto vlastnosti představovat někde na začátku knihy.

Tato kniha rozhodně není průvodcem C# 3.0. Spíše je praktickým průvodcem některými zajímavý-mi vlastnostmi tohoto jazyka. Ačkoliv je kladen důraz na C# 3.0, jsou občas vyzdviženy i vlastnosti C# verze 1.0 a 2.0, o kterých si myslím, že jsou užitečné, ale nejsou moc často používány.

V této knize kromě již zmiňovaných věcí naleznete:

Obrazové ilustrace vzorů, které vám pomohou se soustředit na význam toho, co může vzor ve skutečnosti provádět.

Kvízy, které jsou vztaženy k ilustracím UML diagramů.

Jednoduché "teoretické" kódy, které mohou být přizpůsobeny mnoha situacím.

Tabulky, které dávají vodítko, kdy si vybrat určitý vzor.

Srovnávací tabulky, které ukazují, v čem jsou si vzory podobné a v čem se liší.

Seznam výhod, nevýhod a omezení pro každý vzor.

Všelijaké výzvy a doplňková cvičení, které pomohou prohloubit vaše znalosti.

Page 14: C# - návrhové vzory

12

Co potřebujete pro použití této knihyPro spuštění programů v této knize potřebujete:

Počítač s Windows XP nebo novějším. Kompatibilními platformami jsou jakákoli PC nebo na Intelu založený Mac s virtuálním strojem.

Microsoft .NET Framework 3.5. Stahujte z http://www.microsoft.com/downloads.

Editor kódu nebo celé vývojové prostředí. Ačkoliv Visual Studio 2008 (nebo novější verze) je ideálním doprovodem k programování v C# 3.0, není nezbytné.

Dokumentaci k C# 3.0, kterou naleznete na http://msdn2.microsoft.com/vcsharp.

Konvence použité v této knizePro lepší přehlednost kniha používá následující typografické zásady:

Neproporcionální písmo. Použito pro výpisy kódů, příkazy, nastavení, proměnné, atributy, funk-ce, typy, třídy, jmenné prostory, metody, vlastnosti, parametry, hodnoty, objekty, události a XML značky. Také se používá pro URL adresy nebo názvy souborů.

NeproporcionálníNeproporcionální písmopísmo tučné.tučné. Použito pro zvýraznění částí ve výpisech kódů.

Text tohoto šedého rámečku může obsahovat tip, doporučení, nebo obecnou poznámku.

Sdělte nám svůj názorJako čtenáři této knihy se stáváte těmi nejdůležitějšími kritiky a komentátory. Vážíme si vašeho názoru a chtěli bychom vědět, co děláme správně, co bychom mohli dělat lépe, ve kterých oblastech bychom měli publikovat, a také vaše další podnětné myšlenky, o které jste ochotni se podělit.

Jako odborný redaktor Zoner Press vítám vaše názory. Můžete mi psát – poslat e-mail nebo dopis – a sdělit mi, co se vám v této knize lí bilo nebo nelíbilo, stejně tak, co bychom měli udělat, aby naše další knihy byly lepší. Pokud mi napíšete, nezapomeňte, prosím, připojit název knihy, ISBN, jméno autora, vaše jméno, telefon, fax nebo e-mail. Pozorně zhodnotím vaše názory a poskytnu je všem lidem, kteří pracovali na této knize.

Prosím, vězte, že nemohu pomoci s technickými problémy, které se týkají obsahu knihy, a že díky velkému množství e-mailů, jež dostávám, nemohu zaručit odpověď na každou zprávu.

E-mail: [email protected] nebo [email protected].

Adresa: ZonerPress

ZONER software, a.s.

Miroslav Kučera

Nové sady 18, 602 00 Brno

Page 15: C# - návrhové vzory

13

Poděkování Můj první dík patří Johnu Osbornovi, mému editorovi ve vydavatelství O'Reilly, za udržení víry a vydání knihy v termínu. Velmi oceňuji jeho péči a znalosti. Dále Jeffovi Peperovi, který tuto kni-hu v rychlosti prohlédnul. Mrzí mě, že jsme ji nemohli projít společně. Také děkuji následujícím recenzentům: Eric Lippert, Jim Whitehead, Stefan Gruner a Pierre-Henri Kuaté. Jejich konkrétní poznámky vedly k mnoha revizím a celkově k mnohem lepší knize. Musím také zmínit mé odděle-ní na University of Pretoria, které mi poskytlo nejnovější technické vybavení. Nesmím opomenout své kolegy, kteří mi dali čas koncentrovat se, když jsem to potřebovala.

Dále děkuji Janovi Eloffovi za jeho podporu a přátelství. Musím zmínit i Carla Ghezziho z Politec-nico di Milano, který mě laskavě hostil v létě 2007, když už byla napsána většina rukopisu. Moji dřívější studenti Hans Lombard a D-J Miller mi pomohli s několika příklady a já opravdu oceňuji jejich svěžího ducha a věnování se úkolu.

Psaní této knihy by bylo mnohem méně zábavné bez neustálé podpory a zájmu mých dobrých přátel, kterými jsou Nigel Horspool, Rob Koenig a Rudolph Vosser. Nikdy přesně nevěděli, kdy bude kniha dokončena, ale ve své podpoře vytrvali, takže kniha byla nakonec úspěšně dokončena. A úplně nakonec děkuji své matce, mým synům a mé rodině, jejichž láska a podpora se mě držela po celou dobu psaní této (a jiných) knihy – děkuji vám moc.

– Judith BishopováPretoria, Jihoafrická republika

Říjen 2007

Page 16: C# - návrhové vzory

14

Page 17: C# - návrhové vzory

65C# – návrhové vzory

Strukturální vzory Composite (Kompozit) a Flyweight (Muší váha) se týkají systémů, které mají mnoho datových objektů. Vzor Composite je široce aplikovatelný, a při jeho skládání je možné použít i vzor Flyweight. Vzor Flyweight sdílí identické objekty bez vědomí uživatele, aby ušetřil paměť. Tyto vzory ve svých implementacích používají následující vlastnosti jazyka C#:

Generické typy (generics).

Vlastnosti (properties).

Struktury.

Indexery.

Implicitní typování.

Inicializátory.

Anonymní typy.

Vzor Composite ( Kompozit)

ÚčelVzor Composite vytváří strukturované hierarchie, což znamená, že s jednotlivými komponentami lze pracovat úplně stejně jako se skupinami komponent. Typické operace na komponentách zahr-nují přidávání, odstraňování, zobrazení, vyhledávání a seskupování.

3 Strukturální vzory:

Composite a Flyweight

Page 18: C# - návrhové vzory

66 Kapitola 3 – Strukturální vzory: Composite a Flyweight

IlustracePočítačových aplikací, které se specializují na seskupování dat, existuje velké množství. Stačí se podívat na hudební playlist v iTunes nebo album digitálních fotografií na Flickr.com nebo iPhoto (obrázek 3.1). Položky jsou umístěny v dlouhém seznamu, který je poté doplněn o strukturu.

Obrázek 3.1. Ilustrace vzoru Composite v aplikaci iPhoto.

Na obrázku z aplikace iPhoto lze vidět, že existují různé způsoby pro prohlížení importovaných fotek – chronologicky nebo podle názvu. Jedna fotka se může objevit v mnoha albech (například v albech s názvy Last Roll, 2007 a Switzerland). Vytvoření nového alba vede k vytvoření nového objektu Composite, což ale nemá za následek zkopírování fotky. V tomto kontextu musíme zmínit důležitou informací o vzoru Composite – operace, které jsou prováděny na fotografiích a albech, by měly mít stejný název i výsledný efekt, ačkoliv jejich implementace mohou být odlišné. Uživatel by měl být schopen například zobrazit konkrétní fotografii nebo album (které obsahuje fotografie). Operace vedoucí k odstranění fotografie či alba by se rovněž měla jmenovat a chovat stejně.

NávrhVzor Composite patří mezi ty nejjednodušší. Pracuje se dvěma typy objektů: Components a Com-posites (kompozity složené z komponent). Oba typy se přizpůsobují společnému rozhraní, které definuje běžné operace. Objekty Composite se skládají z Component, přičemž operace na Com-posite jsou ve většině případů implementovány zavoláním ekvivalentních operací na objektech Component. Podívejte se na obrázek 3.2 s UML diagramem tohoto vzoru.

Page 19: C# - návrhové vzory

67C# – návrhové vzory

Obrázek 3.2. UML diagram vzoru Composite.

Základními účastníky v UML diagramu vzoru Composite jsou:

IComponent. Definuje operace pro složené objekty a nějaké standardní chování, které bude aplikovatelné na oba typy objektů.

Operation. Operace na objektech, které vyhovují rozhraní IComponent.

Component. Implementuje operace, které jsou aplikovatelné na jeden objekt, který již ne-může být dále rozložen.

Composite. Implementuje operace, které jsou aplikovatelné na složené objekty. Pro tyto úče-ly využívá lokálně udržovaný seznam komponent a pravděpodobně používá ekvivalentní operace Component.

Klient používá pouze rozhraní IComponent, což mu značně zjednodušuje práci.

Kvíz

Spojte účastníky vzoru Composite s aplikací iPhoto Abychom otestovali, zdali rozumíte vzoru Composite, zakryjte levý sloupec této tabulky a pokuste se identifi kovat účastníky vzoru s položkami z ilustračního příkladu (viz obrázek 3.1) v pravém sloupci. Následně porovnejte své odpovědi s levým sloupcem.

IComponent Viditelná entita v iPhoto

Component Jedna fotografi e

Composite Album s fotografi emi

Operation Otevření a prohlížení

ImplementaceAčkoliv naše ilustrace se odkazuje na fotky a alba, návrh a implementace vzoru Composite je kom-pletně nezávislá na druhu spravované komponenty. Stejně dobře bychom mohli pracovat například

Page 20: C# - návrhové vzory

68 Kapitola 3 – Strukturální vzory: Composite a Flyweight

se skupinami lidí nebo s portfoliem bankovních účtů. Operace objektu Composite musí iterovat strukturami těchto komponent. Abychom si uvědomili flexibilitu komponenty libovolného typu a spojení mezi listy a Composite, můžeme použít generické typy, což je vlastnost jazyka C#.

Vlastnost jazyka C# – Generické typy

Generické typy jsou rozšířením systému typů. Znamená to, že struktury, třídy, rozhraní, delegáti a me-tody mohou být parametrizovány prostřednictvím dalších typů. Například generický typ List<T> je generátor pro typy jako List<String> a List<Person>. Všechny kolekce v knihovně .NET Fra-meworku, které jsou použity v C#, jsou dostupné v generické formě. Zahrnují Dictionary, Stack, Queue a List a jejich variace. Existují také generické metody jako Sort a BinarySearch. Ty vyžadu-jí, aby typy, se kterými pracují, implementovali rozhraní ICompare, takže porovnání prvků může být prováděno správně.

Pro specifi kaci generického typu nebo metody použijte generické parametry ve špičatých závorkách, jako <T>, nebo <T, P>. Generické typy mohou být použity pro specifi kaci dalších generických prvků (opět s použitím formátu <T>), nebo mohou být použity přímo jako typ (jako například T).

Pro konstrukci konkrétního typu nebo metody z jejich generických protějšků stačí doplnit typy každé-ho generického parametru, jako například <string>.

Zdroj: Specifi kace C#, verze 3.0, září 2007, sekce 10.1.3.

Deklarováním IComponent, Component a Composite jako generické typy vytvoříme implementaci vzoru Composite, která pak může být instanciována pro konkrétní použití.

Poznámka. Pro vzor Composite nebudeme vytvářet program, ale jmenný prostor obsahující dvě třídy, Composite a Component , a rozhraní IComponent.

Začneme s rozhraním IComponent a deklarujeme ho jako generický typ s parametrem T. Pak ná-sledují všechny předpokládané operace:

public interface IComponent <T> {

void Add(IComponent <T> c);

IComponent <T> Remove(T s);

IComponent <T> Find(T s);

string Display(int depth);

T Item {get; set;}

}

Poznámka. Protože typy budou v samostatném jmenném prostoru, musí být deklarovány jako veřej-né.

Page 21: C# - návrhové vzory

141C# – návrhové vzory

Vytvářecí vzory zavádí velmi populární koncept v návrhových vzorech: továrny (factory). Továrny jsou třídy, které vytváří instance objektů bez přímého používání podtříd. V kapitole 5 jsme viděli, jak vzor Factory Method (Tovární metoda) může skrýt název třídy před místem, kde je objekt in-stanciován. Vzor Abstract Factory (Abstraktní továrna) jde o krok dál – vytváří rodiny příbuzných nebo závislých objektů. Vzor Builder (Stavitel) dále rozšiřuje tuto flexibilitu při vytváření složitěj-ších struktur provázaných objektů.

Vzor Abstract Factory (Abstraktní továrna)

ÚčelTento vzor podporuje vytváření produktů, které existují v rodinách a jsou navrženy tak, aby byly produkovány společně. Abstraktní továrna může být upravena pro konkrétní továrny, z nichž kaž-dá může vytvářet různé produkty různých typů a v různých kombinacích. Vzor izoluje definice produktů a názvy jejich tříd od klienta, takže jediný způsob, jak získat jejich instance, je přes to-várnu. Z tohoto důvodu mohou být rodiny produktů jednoduše zaměněny nebo aktualizovány bez nutnosti změnit klienta.

IlustraceMetlou moderní společnosti je velké množství padělků na trhu. Produkty mnoha známých značek jsou kopírovány a prodávány často jako originály. Někdy jsou kopie předem označeny jako repliky, takže zákazník je si vědom toho, co kupuje. Často ale zákazník neví (nebo se o to vůbec nezajímá),

6Vytvářecí vzory:

Abstract Factory a Builder

Page 22: C# - návrhové vzory

142 Kapitola 6 – Vytvářecí vzory: Abstract Factory a Builder

z jaké továrny zboží vlastně pochází. Obrázek 6.1 ukazuje některé repliky kabelek – vypadají jako kabelky od Gucciho, ale mohly by pocházet z továrny s názvem Poochy ("Půči"; smyšlené jméno).

Obrázek 6.1. Ilustrace vzoru Abstract Factory – replika kabelek od Gucciho (Poochy).

Vzor Abstract Factory vytváří podobnou vrstvu neprůhlednosti tím, že schovává název továrny před klientem. Z hlediska programátora to umožňuje zaměňovat továrny, zatímco stále vyrábí zbo-ží v souladu s dohodnutým rozhraním.

NávrhVzor Abstract Factory má mnoho účastníků, jak je ukázáno v následujícím UML diagramu (viz obrázek 6.2), ale návrh je ve skutečnosti docela jednoduchý. Klient má konkrétní továrnu odpo-vídající rozhraní AbstractFactory. Skrz něj žádá o objekty produktů (zde typu A a B). Toto jsou ale abstraktní typy produktů. Až konkrétní třídy továren rozhodují o tom, které produkty klient dostane. To systému umožňuje být nezávislý na způsobech, jak jsou produkty vytvářeny a imple-mentovány. Klient se nezajímá o detaily produktu nebo o jejich aktuální názvy tříd – ví pouze to, že je poskytován objekt typu A nebo objekt typu B.

Z formálního hlediska jsou účastníci tohoto vzoru tito:

AbstractFactory. Rozhraní s operací Create pro každý abstraktní produkt.

Factory1, Factory2. Implementace všech vytvářecích operací AbstractFactory.

AbstractProduct. Rozhraní pro jednotlivé druhy produktů s vlastními operacemi.

ProductA1, ProductA2, ProductB1, ProductB2. Třídy, které implementují rozhraní Abs-tractProduct a definují objekty produktu tak, aby mohly být vytvořeny odpovídajícími továrnami.

Client. Třída, která přistupuje jen k rozhraní AbstractFactory a AbstractProduct.

Zajímavý aspekt vzoru Abstract Factory je ten, že celá rodina produktů může být změněna za běhu aplikace. Pokud například klient používá rodinu objektů vytvořených pomocí FactoryA, může in-stanciovat FactoryB a přepnout na ni. Protože produkty implementují stejné abstraktní rozhraní, jejich operace budou stejné, ale jejich implementace se mohou lišit.

Page 23: C# - návrhové vzory

143C# – návrhové vzory

Obrázek 6.2. UML diagram vzoru Abstract Factory.

Kvíz

Spojte účastníky vzoru Abstract Factory s ilustrací repliky kabelkyAbychom otestovali, zdali rozumíte vzoru Abstract Factory, zakryjte levý sloupec této tabulky a po-kuste se identifi kovat účastníky vzoru s položkami z ilustračního příkladu (viz obrázek 6.1) v pravém sloupci. Následně porovnejte své odpovědi s levým sloupcem.

Client Zákazník kupující kabelku

AbstractFactory Vrací kabelku

FactoryA Gucci

FactoryB Poochy

AbstractProduct Kabelky

PorductA1 Pravé kabelky

ProductB1 Repliky kabelek