Programovanie

Pohľad na dizajnový vzor Composite

Druhý deň som počúval národné verejné rádio Car Talk, populárne týždenné vysielanie, počas ktorého sa volajúci pýtajú na svoje vozidlá. Pred každou programovou prestávkou hostitelia prehliadky požiadajú volajúcich, aby vytočili číslo 1-800-CAR-TALK, čo zodpovedá číslu 1-800-227-8255. Samozrejme, prvé sa pamätá oveľa ľahšie ako druhé, čiastočne preto, že slová „CAR TALK“ sú zložené: dve slová, ktoré predstavujú sedem číslic. Ľudia majú vo všeobecnosti jednoduchšie zaobchádzať s kompozitmi, ako s ich jednotlivými súčasťami. Rovnako tak pri vývoji objektovo orientovaného softvéru je často vhodné manipulovať s kompozitmi rovnako, ako manipulujete s jednotlivými komponentmi. Táto premisa predstavuje základný princíp kompozitného návrhového vzoru, o ktorom sa pojednáva Dizajnové vzory Java splátka.

Kompozitný vzor

Predtým, ako sa ponoríme do kompozitného vzoru, musím najskôr definovať zložené objekty: predmety, ktoré obsahujú ďalšie predmety; napríklad môže byť kresba zložená z grafických primitív, ako sú čiary, kruhy, obdĺžniky, text atď.

Vývojári v jazyku Java potrebujú kompozitný vzor, ​​pretože s kompozitmi musíme často manipulovať úplne rovnako ako s primitívnymi objektmi. Napríklad musia byť nakreslené, presunuté a zmenené veľkosť základných grafických prvkov, ako sú čiary alebo text. Rovnakú operáciu však chceme vykonať aj pri kompozitoch, ako sú napríklad kresby, ktoré sú zložené z týchto primitívov. V ideálnom prípade by sme chceli vykonávať operácie s primitívnymi objektmi aj s kompozitmi presne rovnakým spôsobom, bez rozdielu medzi týmito dvoma. Ak musíme rozlišovať medzi primitívnymi objektmi a kompozitmi, aby sme mohli vykonať rovnaké operácie na týchto dvoch typoch objektov, náš kód by sa stal zložitejším a náročnejším na implementáciu, údržbu a rozšírenie.

V Dizajnové vzory, autori popisujú kompozitný vzor takto:

Skladajte objekty do stromových štruktúr, ktoré reprezentujú hierarchie jednotlivých častí. Kompozit umožňuje klientom zaobchádzať s jednotlivými objektmi a kompozíciami objektov jednotne.

Implementácia kompozitného vzoru je jednoduchá. Zložené triedy rozširujú základnú triedu, ktorá predstavuje primitívne objekty. Obrázok 1 zobrazuje diagram tried, ktorý ilustruje štruktúru zloženého vzoru.

V schéme tried na obrázku 1 som použil názvy tried z Dizajnový vzor 's Diskusia o zloženom vzore: Komponent predstavuje základnú triedu (alebo prípadne rozhranie) pre primitívne objekty a Zložený predstavuje zloženú triedu. Napríklad Komponent trieda môže predstavovať základnú triedu pre grafické primitívy, zatiaľ čo Zložený trieda môže predstavovať a Kreslenie trieda. Obrázok 1 List trieda predstavuje konkrétny primitívny objekt; napríklad a Riadok trieda alebo a Text trieda. The Prevádzka1 () a Prevádzka2 () metódy predstavujú metódy špecifické pre doménu implementované oboma Komponent a Zložený triedy.

The Zložený trieda udržuje zbierku komponentov. Typicky Zložený metódy sa implementujú iteráciou nad touto kolekciou a vyvolaním príslušnej metódy pre každú z nich Komponent v zbierke. Napríklad a Kreslenie trieda môže implementovať svoje kresliť () metóda, ako je táto:

// Táto metóda je kompozitná metóda public void draw () {// Iterácia nad komponentami pre (int i = 0; i <getComponentCount (); ++ i) {// Získať odkaz na komponent a vyvolať jeho draw metóda Component component = getComponent (i); component.draw (); }} 

Pre každú metódu implementovanú v Komponent triedy, Zložený trieda implementuje metódu s rovnakým podpisom, ktorá iteruje nad zložkami kompozitu, ako to ilustruje kresliť () metóda uvedená vyššie.

The Zložený trieda rozširuje Komponent triedy, takže môžete zloženému zložiť metódu, ktorá očakáva komponent; zvážte napríklad nasledujúcu metódu:

// Táto metóda je implementovaná v triede, ktorá nesúvisí s // triedami komponentov a kompozitov public void repaint (komponentná zložka) {// Komponent môže byť zložený, ale pretože rozširuje // triedu komponentu, táto metóda nemusí // rozlišovať medzi komponentmi a kompozitmi component.draw (); } 

Predchádzajúcou metódou sa odovzdá komponent - buď jednoduchý komponent, alebo kompozit - a potom sa tento komponent vyvolá kresliť () metóda. Pretože Zložený trieda predlžuje Komponent, premaľovať () metóda nemusí rozlišovať medzi komponentmi a kompozitmi - jednoducho vyvolá kresliť () metóda pre komponent (alebo kompozit).

Diagram triedy kompozitných vzorov na obrázku 1 ilustruje jeden problém so vzorom: musíte rozlišovať medzi komponentmi a kompozitmi, keď odkazujete na Komponent, a musíte sa odvolať na špecifickú metódu zloženia, ako je napr addComponent (). Túto požiadavku obvykle spĺňate pridaním metódy, ako napr isComposite (), do Komponent trieda. Táto metóda sa vráti nepravdivé pre komponenty a je prepísaný v Zložený triedy na návrat pravda. Ďalej musíte tiež obsadiť Komponent odkaz na a Zložený napríklad takto:

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

Všimnite si, že addComponent () metóda je odovzdaná a Komponent odkaz, ktorým môže byť buď primitívny komponent alebo kompozit. Pretože touto zložkou môže byť kompozit, môžete ju zložiť do stromovej štruktúry, ako naznačuje vyššie uvedený citát z Dizajnové vzory.

Obrázok 2 zobrazuje alternatívnu implementáciu zloženého vzoru.

Ak implementujete kompozitný vzor na obrázku 2, nemusíte nikdy rozlišovať medzi komponentmi a kompozitmi a nemusíte vrhať Komponent odkaz na a Zložený inštancia. Vyššie uvedený fragment kódu sa teda zmenší na jeden riadok:

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

Ale ak Komponent odkaz v predchádzajúcom fragmente kódu neodkazuje na a Zložený, čo by malo addComponent () robiť? To je hlavný bod sporu pri implementácii kompozitného vzoru na obrázku 2. Pretože primitívne komponenty neobsahujú ďalšie komponenty, nemá pridanie komponentu k inému komponentu zmysel, takže Component.addComponent () metóda môže buď zlyhať potichu, alebo môže spôsobiť výnimku. Pridanie komponentu k inému primitívnemu komponentu sa zvyčajne považuje za chybu, takže uplatnenie výnimky je možno najlepším postupom.

Ktorá implementácia zloženého vzoru - teda tá na obrázku 1 alebo tá na obrázku 2 - funguje najlepšie? To je vždy téma veľkej debaty medzi implementátormi kompozitných vzorov; Dizajnové vzory uprednostňuje implementáciu obrázku 2, pretože nikdy nemusíte rozlišovať medzi komponentmi a kontajnermi a už nikdy nemusíte vykonávať cast. Osobne uprednostňujem implementáciu obrázku 1, pretože mám veľkú averziu voči implementácii metód v triede, ktoré pre daný typ objektu nedávajú zmysel.

Teraz, keď rozumiete zloženému vzoru a tomu, ako ho môžete implementovať, poďme preskúmať príklad zloženého vzoru v rámci JSP (Apache Struts JavaServer Pages).

Kompozitný vzor a dlaždice Struts

Rámec Apache Struts obsahuje knižnicu značiek JSP, známu ako Dlaždice, ktorá vám umožní zostaviť webovú stránku z viacerých JSP. Tiles je vlastne implementácia vzoru CompositeView J2EE (Java 2 Platform, Enterprise Edition), ktorý je založený na Dizajnové vzory Zložený vzor. Predtým, ako prediskutujeme relevantnosť kompozitného vzoru pre knižnicu značiek Tiles, najskôr si prečítajme dôvody Tiles a toho, ako ich používate. Ak už dlaždice Struts poznáte, môžete si prečítať nasledujúce časti a začať čítať v časti „Použite zložený vzor s dlaždicami Struts“.

Poznámka: Viac informácií o vzore J2EE CompositeView si môžete prečítať v mojom dokumente „Webové komponenty ľahko použiteľné pomocou kompozitného zobrazenia“ (JavaWorld, Decembra 2001) článok.

Dizajnéri často vytvárajú webové stránky so súborom samostatných oblastí; napríklad webová stránka obrázka 3 obsahuje bočný panel, hlavičku, oblasť obsahu a pätu.

Webové stránky často obsahujú viac webových stránok s rovnakým rozložením, ako je napríklad rozloženie bočného panela / hlavičky / obsahu / päty na obrázku 3. Struts Tiles vám umožní opätovne použiť obsah aj rozloženie na viacerých webových stránkach. Predtým, ako prediskutujeme toto opätovné použitie, pozrime sa, ako sa rozloženie obrázka 3 tradične implementuje iba pomocou HTML.

Komplexné rozloženia implementujte ručne

Príklad 1 ukazuje, ako môžete implementovať webovú stránku obrázka 3 s HTML:

Príklad 1. Komplexné usporiadanie implementované ručne

    Ručná implementácia zložitých rozložení <% - Jedna tabuľka rozloží všetok obsah pre túto stránku -%>
Odkazy

Domov

Produkty

K stiahnutiu

Biele knihy

Kontaktuj nás

Vitajte v spoločnosti Sabreware, Inc.
Sem sa dostane obsah špecifický pre stránku

Ďakujeme, že ste sa zastavili!

Predchádzajúci JSP má dve hlavné nevýhody: Po prvé, obsah stránky je vložený do JSP, takže nemôžete znova použiť nič z toho, aj keď je pravdepodobné, že bočný panel, hlavička a päta budú rovnaké na mnohých webových stránkach. Po druhé, rozloženie stránky je tiež vložené do tohto JSP, takže ju rovnako nemôžete znova použiť, aj keď mnoho iných webových stránok na tej istej webovej stránke používa rovnaké rozloženie. Môžeme použiť kroky na nápravu prvej nevýhody, ako budem diskutovať ďalej.

Implementujte komplexné rozloženia pomocou JSP

Príklad 2 ukazuje implementáciu webovej stránky z obrázku 3, ktorá používa :

$config[zx-auto] not found$config[zx-overlay] not found