Programování

Pohled na designový vzor Composite

Druhý den jsem poslouchal National Public Radio Car Talk, populární týdenní vysílání, během kterého se volající ptají na svá vozidla. Před každou programovou přestávkou hostitelé show žádají volající, aby vytočili číslo 1-800-CAR-TALK, což odpovídá číslu 1-800-227-8255. První z nich se samozřejmě pamatuje mnohem snáze než druhá, částečně proto, že slova „AUTOMOBIL“ jsou složená: dvě slova, která představují sedm číslic. Lidé obecně považují za jednodušší zacházet s kompozity než s jejich jednotlivými součástmi. Podobně, když vyvíjíte objektově orientovaný software, je často vhodné manipulovat s kompozity, stejně jako manipulujete s jednotlivými komponentami. Tato premisa představuje základní princip kompozitního návrhového vzoru, jehož téma je tématem Java designové vzory splátka.

Složený vzor

Než se ponoříme do kompozitního vzoru, musím nejprve definovat složené objekty: objekty, které obsahují jiné objekty; například může být výkres složen z grafických primitiv, jako jsou čáry, kruhy, obdélníky, text atd.

Vývojáři Java potřebují kompozitní vzor, ​​protože s kompozity musíme často manipulovat přesně stejným způsobem, jako manipulujeme s primitivními objekty. Například grafická primitiva, jako jsou čáry nebo text, musí být nakreslena, přesunuta a změněna jejich velikost. Ale chceme také provést stejnou operaci s kompozity, jako jsou kresby, které jsou složeny z těchto primitiv. V ideálním případě bychom chtěli provádět operace s primitivními objekty i kompozity přesně stejným způsobem, bez rozlišení mezi nimi. Pokud musíme rozlišovat mezi primitivními objekty a kompozity, abychom mohli provádět stejné operace na těchto dvou typech objektů, náš kód by se stal složitějším a obtížněji implementovatelným, udržovatelným a rozšířitelným.

v Designové vzory, autoři popisují kompozitní vzor takto:

Skládejte objekty do stromových struktur, které představují hierarchie celého celku. Kompozitní umožňuje klientům zacházet s jednotlivými objekty a kompozicemi objektů jednotně.

Implementace kompozitního vzoru je snadná. Složené třídy rozšiřují základní třídu, která představuje primitivní objekty. Obrázek 1 ukazuje diagram tříd, který ilustruje strukturu složeného vzoru.

Ve schématu tříd na obrázku 1 jsem použil názvy tříd z Návrhový vzor's Diskuse o složeném vzoru: Součástka představuje základní třídu (nebo případně rozhraní) pro primitivní objekty a Složený představuje složenou třídu. Například Součástka třída může představovat základní třídu pro grafická primitiva, zatímco Složený třída může představovat a Výkres třída. Obrázek 1 List třída představuje konkrétní primitivní objekt; například a Čára třída nebo a Text třída. The Provoz1 () a Provoz2 () metody představují metody specifické pro doménu implementované oběma Součástka a Složený třídy.

The Složený třída udržuje sbírku komponent. Typicky, Složený metody jsou implementovány iterací přes tuto kolekci a vyvoláním příslušné metody pro každou z nich Součástka ve sbírce. Například a Výkres třída může implementovat své kreslit() taková metoda:

// This method is a Composite method public void draw () {// Iterate over the components for (int i = 0; i <getComponentCount (); ++ i) {// Získat odkaz na komponentu a vyvolat její draw metoda Složka složka = getComponent (i); component.draw (); }} 

Pro každou metodu implementovanou v Součástka třída, Složený třída implementuje metodu se stejným podpisem, který iteruje přes komponenty kompozitu, jak ukazuje kreslit() výše uvedená metoda.

The Složený třída rozšiřuje Součástka třídy, takže můžete předat kompozit metodě, která očekává komponentu; zvažte například následující metodu:

// Tato metoda je implementována ve třídě, která nesouvisí s // komponenty a kompozitní třídy public void repaint (komponentní komponenta) {// komponenta může být složená, ale protože rozšiřuje // třídu komponent, nemusí tato metoda // rozlišovat mezi složkami a složenými složkami.draw (); } 

Předchozí metoda je předána komponentě - buď jednoduché komponentě nebo kompozici - a poté vyvolá tuto komponentu kreslit() metoda. Protože Složený třída se prodlužuje Součástkapřekreslit () metoda nemusí rozlišovat mezi komponentami a kompozity - jednoduše vyvolá kreslit() metoda pro komponentu (nebo kompozit).

Diagram třídy kompozitních vzorů na obrázku 1 ilustruje jeden problém se vzorem: musíte rozlišovat mezi komponentami a kompozity, když odkazujete na Součástkaa musíte vyvolat metodu specifickou pro kompozit, například addComponent (). Tento požadavek obvykle splníte přidáním metody, například isComposite (), do Součástka třída. Tato metoda se vrací Nepravdivé pro komponenty a je přepsán v Složený třída k návratu skutečný. Navíc musíte také seslat Součástka odkaz na a Složený například takto:

... if (component.isComposite ()) {Composite composite = (Composite) component; composite.addComponent (someComponentThatCouldBeAComposite); } ... 

Všimněte si, že addComponent () metoda je předána a Součástka odkaz, kterým může být buď primitivní komponenta, nebo kompozit. Protože touto komponentou může být kompozit, můžete komponenty komponovat do stromové struktury, jak naznačuje výše uvedená citace z Designové vzory.

Obrázek 2 ukazuje alternativní implementaci kompozitního vzoru.

Pokud implementujete kompozitní vzor obrázku 2, nemusíte nikdy rozlišovat mezi komponentami a kompozity a nemusíte vrhat Součástka odkaz na a Složený instance. Výše uvedený fragment kódu se tedy zmenší na jeden řádek:

... component.addComponent (someComponentThatCouldBeAComposite); ... 

Ale pokud Součástka odkaz v předchozím fragmentu kódu neodkazuje na a Složený, co by mělo addComponent () dělat? To je hlavní bod sporu s implementací kompozitního vzoru na obrázku 2. Protože primitivní komponenty neobsahují další komponenty, přidávání komponenty k jiné komponentě nemá smysl, takže Component.addComponent () metoda může buď selhat tiše, nebo vyvolat výjimku. Přidání komponenty k jiné primitivní komponentě se obvykle považuje za chybu, takže vyvolání výjimky je možná nejlepší postup.

Která implementace kompozitního vzoru - ta na obrázku 1 nebo ta na obrázku 2 - tedy funguje nejlépe? To je vždy téma velké debaty mezi implementátory kompozitních vzorů; Designové vzory upřednostňuje implementaci obrázku 2, protože nikdy nemusíte rozlišovat mezi komponentami a kontejnery a nikdy nemusíte provádět cast. Osobně dávám přednost implementaci obrázku 1, protože mám silnou averzi k implementaci metod ve třídě, které pro daný typ objektu nedávají smysl.

Nyní, když rozumíte složenému vzoru a jak ho můžete implementovat, prozkoumejme příklad složeného vzoru s rámcem Apache Struts JavaServer Pages (JSP).

Složený vzor a dlaždice vzpěr

Rámec Apache Struts obsahuje knihovnu značek JSP, známou jako Dlaždice, která vám umožňuje skládat webovou stránku z více JSP. Tiles je vlastně implementace vzoru CompositeView J2EE (Java 2 Platform, Enterprise Edition), který je založen na Designové vzory Složený vzor. Předtím, než probereme důležitost kompozitního vzoru pro knihovnu značek Dlaždice, nejprve si přečtěte důvody pro Dlaždice a jak je používáte. Pokud jste již obeznámeni s dlaždicemi Struts, můžete si prohlédnout následující části a začít číst v části „Použití složeného vzoru s dlaždicemi Struts“.

Poznámka: Další informace o vzoru J2EE CompositeView si můžete přečíst v mém „Snadno použitelných komponentách webové aplikace s kompozitním pohledem“ (JavaWorld, Prosince 2001) článek.

Návrháři často vytvářejí webové stránky se sadou samostatných oblastí; například webová stránka obrázku 3 obsahuje postranní panel, záhlaví, oblast obsahu a zápatí.

Webové stránky často obsahují více webových stránek se stejným rozložením, jako je například rozložení postranního panelu / záhlaví / obsahu / zápatí obrázku 3. Struts Tiles vám umožní znovu použít obsah i rozložení na více webových stránkách. Než budeme diskutovat o tomto opětovném použití, podívejme se, jak je rozložení obrázku 3 tradičně implementováno pouze pomocí HTML.

Implementujte složitá rozvržení ručně

Příklad 1 ukazuje, jak můžete implementovat webovou stránku z obrázku 3 pomocí HTML:

Příklad 1. Složité rozvržení implementované ručně

    Ruční implementace složitých rozvržení <% - Jedna tabulka vyloží veškerý obsah pro tuto stránku -%>
Odkazy

Domov

produkty

Soubory ke stažení

bílé papíry

Kontaktujte nás

Vítejte ve společnosti Sabreware, Inc.
Sem se dostane obsah specifický pro stránku

Děkujeme za zastavení!

Předchozí JSP má dvě hlavní nevýhody: Za prvé, obsah stránky je vložen do JSP, takže nemůžete znovu použít žádný z nich, i když boční panel, záhlaví a zápatí budou pravděpodobně stejné na mnoha webových stránkách. Zadruhé, rozložení stránky je také vloženo do tohoto JSP, takže jej také nemůžete znovu použít, i když mnoho dalších webových stránek na stejném webu používá stejné rozložení. Můžeme použít opatření k nápravě první nevýhody, jak budu diskutovat dále.

Implementujte komplexní rozvržení pomocí JSP

Příklad 2 ukazuje implementaci webové stránky z obrázku 3, která používá :