Toisena päivänä kuuntelin National Public Radion Car Talk -ohjelmaa, joka on suosittu viikoittainen lähetys, jonka aikana soittajat esittävät kysymyksiä ajoneuvoistaan. Ennen jokaista ohjelmataukoa ohjelman juontajat pyytävät soittajia soittamaan numeroon 1-800-CAR-TALK, joka vastaa numeroa 1-800-227-8255. Ensin mainittu on tietysti paljon helpompi muistaa kuin jälkimmäinen, osittain siksi, että sanat ”CAR TALK” ovat yhdistelmä: kaksi sanaa, jotka edustavat seitsemää numeroa. Ihmisten on yleensä helpompi käsitellä yhdistelmiä kuin niiden yksittäisiä osia. Samoin oliokeskeisiä ohjelmistoja kehitettäessä on usein kätevää käsitellä koosteita samalla tavalla kuin yksittäisiä komponentteja. Tämä lähtökohta edustaa tämän Java Design Patterns -osion aiheena olevan Composite-suunnittelumallin perusperiaatetta.
- The Composite pattern
- Composite-kuvio ja Struts Tiles
- Toteuta monimutkaiset asettelut käsin
- Esimerkki 1. Monimutkainen ulkoasu käsin toteutettuna
- Kompleksisten ulkoasujen toteuttaminen JSP:n includeilla
- Esimerkki 2. JSP:llä toteutettu monimutkainen ulkoasu sisältää
- Esimerkki 3. sidebar.jsp
- Esimerkki 4. Sidebar.jsp
- Esimerkki 5. content.jsp
- Esimerkki 6. footer.jsp
- Kompleksisten ulkoasujen toteuttaminen Struts Tilesin avulla
- Esimerkki 7. Struts Tilesin käyttö asettelun kapselointiin
- Esimerkki 8. WEB-INF/tiles-defs.xml
- Esimerkki 9. header-footer-sidebar-layout.jsp
- Composite-kuvion käyttäminen Struts Tilesin kanssa
- Esimerkki 10. WEB-INF/tiles-defs.xml: Composite-mallin käyttö
- Esimerkki 11:n sidebar-layout.jsp: Esimerkki 11:n asettelu. sidebar-layout.jsp
- Esimerkki 12. flags.jsp
- Esimerkki 13. sidebar-links.jsp
- Tänä päivänä kaikki on komposiitteja
- Kotitehtävä
- Kotitehtävä viime kerrasta
- Esimerkki H1. flags.jsp
- Esimerkki H2. WEB-INF/web.xml (Ote)
- Esimerkki H3. WEB-INF/struts-config.xml
- Esimerkki H4. WEB-INF/classes/actions/FlagAction.java
- Esimerkki H5. WEB-INF/web.xml (Ote)
- Esimerkki H6. sidebar-links.jsp
- Esimerkki H7. header.jsp
- Esimerkki H8. content.jsp
- Esimerkki H9. footer.jsp
- Esimerkki H10. WEB-INF/classes/resources_en.properties
- Esimerkki H11. WEB-INF/classes/resources_zh.properties
- Sähköposti
- Learn more about this topic
The Composite pattern
Ennen kuin sukellamme Composite-malliin, on ensin määriteltävä composite-objektit: objektit, jotka sisältävät muita objekteja; esimerkiksi piirros voi koostua graafisista primitiiveistä, kuten viivoista, ympyröistä, suorakulmioista, tekstistä ja niin edelleen.
Javan kehittäjät tarvitsevat Composite-kuviota, koska meidän on usein manipuloitava komposiitteja täsmälleen samalla tavalla kuin primitiivisiä objekteja. Esimerkiksi graafisia primitiivejä, kuten viivoja tai tekstiä, on piirrettävä, siirrettävä ja muutettava kokoa. Haluamme kuitenkin suorittaa samat operaatiot myös komposiiteille, kuten piirustuksille, jotka koostuvat kyseisistä primitiiveistä. Ihannetapauksessa haluaisimme suorittaa operaatiot sekä primitiivisille objekteille että koosteille täsmälleen samalla tavalla erottelematta niitä toisistaan. Jos meidän täytyy tehdä ero primitiivisten objektien ja komposiittien välillä suorittaaksemme samoja operaatioita näille kahdelle objektityypille, koodistamme tulisi monimutkaisempaa ja vaikeampaa toteuttaa, ylläpitää ja laajentaa.
Suunnittelumalleissa kirjoittajat kuvaavat Komposiitti-mallia näin:
Kompositoi objekteja puurakenteiksi esittääksesi osa-kokonaisuus-hierarkioita. Komposiitin avulla asiakkaat voivat käsitellä yksittäisiä objekteja ja objektien koostumuksia yhdenmukaisesti.
Komposiittimallin toteuttaminen on helppoa. Komposiittiluokat laajentavat perusluokkaa, joka edustaa primitiivisiä objekteja. Kuvassa 1 on luokkakaavio, joka havainnollistaa Composite-kuvion rakennetta.
Kuvion 1 luokkakaaviossa käytin luokkien nimiä Design Patternin Composite-kuvion keskustelusta: Component
edustaa primitiivisten objektien perusluokkaa (tai mahdollisesti rajapintaa), ja Composite
edustaa komposiittiluokkaa. Esimerkiksi Component
-luokka voisi edustaa graafisten primitiivien perusluokkaa, kun taas Composite
-luokka voisi edustaa Drawing
-luokkaa. Kuvan 1 Leaf
-luokka edustaa konkreettista primitiivistä objektia; esimerkiksi Line
– tai Text
-luokkaa. Operation1()
– ja Operation2()
-metodit edustavat toimialuekohtaisia metodeja, jotka on toteutettu sekä Component
– että Composite
-luokissa.
Composite
-luokka ylläpitää komponenttikokoelmaa. Tyypillisesti Composite
-metodit toteutetaan iteroimalla tuon kokoelman yli ja kutsumalla sopivaa metodia jokaiselle Component
:lle kokoelmassa. Esimerkiksi Drawing
-luokka voi toteuttaa draw()
-metodinsa näin:
Kunkin Component
-luokassa toteutetun metodin kohdalla Composite
-luokka toteuttaa metodin, jolla on sama allekirjoitus ja joka iteroi koosteen komponenttien yli, kuten edellä mainittu draw()
-metodi osoittaa.
Luokka Composite
laajentaa luokkaa Component
, joten voit välittää komposiitin metodille, joka odottaa komponenttia; tarkastellaan esimerkiksi seuraavaa metodia:
// This method is implemented in a class that's unrelated to the// Component and Composite classespublic void repaint(Component component) { // The component can be a composite, but since it extends // the Component class, this method need not // distinguish between components and composites component.draw();}
Edelliselle metodille välitetään komponentti – joko pelkkä komponentti tai komposiitti – ja sitten se kutsuu tuon komponentin draw()
-metodia. Koska Composite
-luokka laajentaa Component
-luokkaa, repaint()
-metodin ei tarvitse erottaa komponentteja ja komposiitteja toisistaan – se vain kutsuu komponentin (tai komposiitin) draw()
-metodia.
Kuvion 1 Composite-kuvion luokkakaavio havainnollistaa kuitenkin yhden ongelman kuvion kanssa: komponentit ja komposiitit on erotettava toisistaan, kun viitataan Component
-luokkaan, ja on kutsuttava komposiittikohtaista metodia, kuten addComponent()
. Tämä vaatimus täytetään yleensä lisäämällä Component
-luokkaan metodi, kuten isComposite()
. Kyseinen metodi palauttaa false
komponenteille, ja se ohitetaan Composite
-luokassa palauttamaan true
. Lisäksi Component
-viittaus on casteroitava Composite
-instanssiksi näin:
Huomaa, että addComponent()
-metodille välitetään Component
-viittaus, joka voi olla joko primitiivinen komponentti tai komposiitti. Koska tuo komponentti voi olla komposiitti, voit koota komponentteja puurakenteeksi, kuten edellä mainittu lainaus Design Patternsista osoittaa.
Kuvassa 2 on esitetty vaihtoehtoinen Composite-kuvion toteutus.
Jos toteutat kuvion 2 Composite-kuvion, sinun ei tarvitse koskaan erottaa komponentteja ja komposiitteja toisistaan, eikä sinun tarvitse castata Component
-viittausta Composite
-instanssiksi. Niinpä edellä mainittu koodinpätkä pelkistyy yhdeksi riviksi:
...component.addComponent(someComponentThatCouldBeAComposite);...
Mutta jos edellisen koodinpätkän Component
-viittaus ei viittaa Composite
:iin, mitä addComponent()
:n pitäisi tehdä? Tämä on merkittävä kiistakohta kuvan 2 Composite-kuvion toteutuksessa. Koska primitiiviset komponentit eivät sisällä muita komponentteja, komponentin lisääminen toiseen komponenttiin ei ole järkevää, joten Component.addComponent()
-metodi voi joko epäonnistua äänettömästi tai heittää poikkeuksen. Tyypillisesti komponentin lisääminen toiseen primitiiviseen komponenttiin katsotaan virheeksi, joten poikkeuksen heittäminen on ehkä paras toimintatapa.
Kumman Composite-kuvion toteutus – kuvion 1 vai kuvion 2 – toimii siis parhaiten? Siitä käydään aina suurta keskustelua Composite-kuvion toteuttajien kesken; Design Patterns suosii kuvan 2 toteutusta, koska komponentteja ja kontteja ei tarvitse koskaan erottaa toisistaan, eikä castia tarvitse koskaan tehdä. Henkilökohtaisesti pidän enemmän kuvion 1 toteutuksesta, koska minulla on voimakas vastenmielisyys toteuttaa luokkaan metodeja, jotka eivät ole järkeviä kyseisen objektityypin kannalta.
Nyt kun ymmärrät Composite-kuvion ja sen toteuttamisen, tarkastellaanpa Composite-kuvion esimerkkiä Apache Struts JavaServer Pages (JSP) -puitteiston avulla.
Composite-kuvio ja Struts Tiles
Apache Struts -kehys sisältää JSP-tunnistekirjaston, joka tunnetaan nimellä Tiles ja jonka avulla voit koota WWW-sivun useista JSP:istä. Tiles on itse asiassa J2EE:n (Java 2 Platform, Enterprise Edition) CompositeView-kuvion toteutus, joka puolestaan perustuu Design Patterns Composite-kuvioon. Ennen kuin keskustelemme Composite-mallin merkityksestä Tiles-tunnistekirjastolle, käydään ensin läpi Tilesin perusteet ja sen käyttötavat. Jos Struts Tiles on sinulle jo tuttu, voit ohittaa seuraavat kappaleet ja aloittaa lukemisen kohdasta ”Use the Composite Pattern with Struts Tiles.”
Huomautus: Voit lukea lisää J2EE CompositeView -kuviosta artikkelistani ”Web Application Components Made Easy with Composite View” (JavaWorld, joulukuu 2001).
Suunnittelijat rakentavat Web-sivut usein joukosta erillisiä alueita; esimerkiksi kuvan 3 Web-sivu koostuu sivupalkista, otsikosta, sisältöalueesta ja alatunnisteesta.
Websivustot sisältävät usein useita Web-sivuja, joilla on identtiset asettelut, kuten kuvan 3 sivupalkki/otsikko/sisältö/footer-asettelu. Struts Tilesin avulla voit käyttää sekä sisältöä että ulkoasua uudelleen useiden Web-sivujen välillä. Ennen kuin keskustelemme tästä uudelleenkäytöstä, katsotaan, miten kuvan 3 asettelu on perinteisesti toteutettu pelkällä HTML:llä.
Toteuta monimutkaiset asettelut käsin
Esimerkki 1 näyttää, miten voit toteuttaa kuvan 3 verkkosivun HTML:llä:
Esimerkki 1. Monimutkainen ulkoasu käsin toteutettuna
Edellisessä JSP:ssä on kaksi suurta haittaa: Ensinnäkin sivun sisältö on upotettu JSP:hen, joten mitään siitä ei voi käyttää uudelleen, vaikka sivupalkki, otsikko ja alatunniste ovat todennäköisesti samat monilla Web-sivuilla. Toiseksi sivun ulkoasu on myös upotettu kyseiseen JSP:hen, joten sitäkään ei voi käyttää uudelleen, vaikka monet muut saman verkkosivuston verkkosivut käyttävät samaa ulkoasua. Voimme käyttää <jsp:include>
-toimintoa ensimmäisen epäkohdan korjaamiseen, kuten seuraavaksi käsittelen.
Kompleksisten ulkoasujen toteuttaminen JSP:n includeilla
Esimerkissä 2 on kuvassa 3 esitetyn Web-sivun toteutus, jossa käytetään <jsp:include>
:
Esimerkki 2. JSP:llä toteutettu monimutkainen ulkoasu sisältää
Edellinen JSP sisältää muiden JSP:iden sisältöä <jsp:include>
:llä. Koska olen kapseloinut tuon sisällön erillisiin JSP:iin, voit käyttää sitä uudelleen muilla WWW-sivuilla:
Täydellisyyden vuoksi olen luetellut alla edellisen JSP:n sisältämät JSP:t:
Esimerkki 4. Sidebar.jsp
. header.jsp
<font size='6'>Welcome to Sabreware, Inc.</font><hr>
Esimerkki 5. content.jsp
<font size='4'>Page-specific content goes here</font>
<hr>Thanks for stopping by!
Vaikka Esimerkin 2 JSP:ssä käytetäänkin <jsp:include>
:aa sisällön uudelleenkäyttöön, sivun ulkoasua ei voi uudelleenkäyttää, koska se on kovakoodattu kyseiseen JSP:hen. Struts Tiles mahdollistaa sekä sisällön että ulkoasun uudelleenkäytön, kuten seuraavassa kappaleessa havainnollistetaan.
Kompleksisten ulkoasujen toteuttaminen Struts Tilesin avulla
Esimerkissä 7 näytetään kuvassa 3 esitetty verkkosivu toteutettuna Struts Tilesin avulla:
Esimerkki 7. Struts Tilesin käyttö asettelun kapselointiin
Edeltävässä JSP:ssä käytetään <tiles:insert>
-tagia kuvan 3 JSP:n luomiseen. Kyseinen JSP on määritelty tiles-määritelmällä nimeltä sidebar-header-footer-definition
. Tämä määritelmä sijaitsee Tiles-konfiguraatiotiedostossa, joka tässä tapauksessa on WEB-INF/tiles-defs.xml
, joka on lueteltu esimerkissä 8:
Esimerkki 8. WEB-INF/tiles-defs.xml
Edellinen Tiles-määrittely määrittää sivun asettelun, joka on kapseloitu muotoon header-footer-sidebar-layout.jsp
, ja sivun sisällön, joka on kapseloitu muotoon sidebar.jsp
, header.jsp
, content.jsp
ja footer.jsp
, kuten esimerkissä 3-6 luetellaan. Esimerkissä 9 luetellaan JSP, joka määrittelee asettelun-header-footer-sidebar-layout.jsp
:
Edellinen JSP kapseloi asettelun ja lisää sisällön sivupalkki-, editori-, sisältö- ja alatunnistealueille Tiles-määritystiedostossa määritettyjen arvojen mukaisesti, mikä helpottaa sekä sisällön että asettelun uudelleenkäyttöä. Voit esimerkiksi määritellä toisen Tiles-määrittelyn, jossa on sama ulkoasu, sama sivupalkki, editori ja alatunniste, mutta erilainen sisältö:
Luoaksesi Tiles-määrittelyn a-different-sidebar-header-footer-definition
määrittelemän JSP:n, käytät <tiles:insert>
-tunnistetta näin:
Strutsin Tiles-määrittelyn ansiosta voit uudelleenkäyttää sekä sisällön että ulkoasun, mikä osoittautuu korvaamattoman arvokkaaksi sivustoissa, joissa on paljon JSP:itä, jotka jakavat ulkoasun ja jonkin verran sisältöä. Mutta jos tarkastelet tarkkaan esimerkkien 7-9 koodia, huomaat, että sivupalkin alueen ulkoasu on kovakoodattu kohtaan sidebar.jsp
, joka on lueteltu esimerkissä 3. Tämä tarkoittaa, että kyseistä asettelua ei voi käyttää uudelleen. Onneksi Tiles-tunnistekirjasto toteuttaa Composite-mallin, jonka avulla aluetta varten voidaan määrittää JSP:n sijasta tiles-määrittely. Seuraavassa kappaleessa selitän, miten tuota Composite-kuvion toteutusta käytetään.
Composite-kuvion käyttäminen Struts Tilesin kanssa
Struts Tiles toteuttaa Composite-kuvion, jossa Component
-luokkaa edustavat JSP:t ja Composite
-luokkaa edustaa Tiles-määrittely. Tämän toteutuksen avulla voit määrittää JSP:n alueen sisällöksi joko JSP:n (komponentti) tai Tiles-määrittelyn (komposiitti). Esimerkki 10 havainnollistaa tätä ominaisuutta:
Esimerkki 10. WEB-INF/tiles-defs.xml: Composite-mallin käyttö
Edellinen Tiles-konfiguraatiotiedosto määrittelee kaksi Tiles-määritelmää: sidebar-definition
ja sidebar-header-footer-definition
. sidebar-definition
määritetään sivupalkin alueen arvoksi sidebar-header-footer-definition
:ssä. Se voidaan määrittää sellaisenaan, koska Tiles toteuttaa Composite-mallin antamalla Tilesin määrittää määritelmän (Composite
, joka on JSP-kokoelma) siinä, missä normaalisti määritetään yksittäinen JSP (joka on Component
).
Sivupalkin asettelu on koteloitu esimerkin 11 sidebar-layout.jsp
:
Esimerkki 12 listaa flags.jsp
, joka on määritetty sivupalkin top
-alueen sisällöksi, ja esimerkki 13 listaa sidebar-links.jsp
, joka on määritetty sivupalkin bottom
-alueeksi:
Esimerkki 12. flags.jsp
Nyt sidebar-definition
voi määritellä muitakin alueita, joilla on ylä- ja alakomponentti, vaikkakin sinun pitäisi luultavasti nimetä määritelmä uudelleen joksikin yleisemmäksi, kuten top-bottom-definition
.
Tänä päivänä kaikki on komposiitteja
Komposiittimalli on suosittu esityskehysten, kuten Swingin ja Strutsin, parissa, koska sen avulla voit nestata kontteja käsittelemällä komponentteja ja niiden kontteja täsmälleen samalla tavalla. Struts Tiles käyttää Composite-mallia määrittelemään yksinkertaisen JSP:n tai Tiles-määrittelyn – joka on kokoelma JSP:tä – laatan sisällöksi. Tämä on tehokas ominaisuus, joka helpottaa eri ulkoasuja sisältävien suurten sivustojen hallintaa.
Alempana olevassa ”Kotitehtävä viime kerrasta” -osiossa laajennetaan tämän artikkelin keskustelua kansainvälistämällä edellinen sovellus Struts-toiminnolla ja JSP-standardimerkkikirjastolla (JSP Standard Tag Library, JSTL).
Kotitehtävä
Keskustelkaa siitä, miten Swing toteuttaa komposiittikuvioinnin luokkien Component
ja Container
avulla.
Kotitehtävä viime kerrasta
Viimeisessä tehtävässä sinua pyydettiin lataamaan Struts osoitteesta http://jakarta.apache.org/struts/index.html ja toteuttamaan oma Struts-toimintoluokka.
Tässä tehtävässä päätin toteuttaa Struts-toimintoluokan yhdessä JSP Standard Tag Library (JSTL) -kirjaston (JSP Standard Tag Library) kanssa Kansainvälistääksesi Esimerkin 1 web-sovelluksen. Vaikka Struts tarjoaa tarvittavan infrastruktuurin web-sovellusten kansainvälistämiseen, sinun kannattaa käyttää JSTL:ää tähän tehtävään, koska JSTL on standardi. Jossain vaiheessa Strutsin kansainvälistämisominaisuudet todennäköisesti poistuvat käytöstä tai ne integroidaan JSTL:ään.
Kun olin kansainvälistänyt Esimerkin 1 Web-sovelluksen Struts-toiminnolla ja JSTL:llä, lokalisoin kyseisen sovelluksen kiinaksi. Kuva H1 havainnollistaa tulosta.
Huomaa: En osaa sanaakaan kiinaa, saati miten kieltä kirjoitetaan, joten kuvan H1 kiinan kieli on valmistettu mielivaltaisista Unicode-merkkijonoista. Se näyttää kuitenkin siistiltä.
Huomaa, että määrittelin href
-attribuutit esimerkin 12 flags.jsp
tyhjiksi merkkijonoiksi, joten kun klikkaat lippuja, servlet-säiliö lataa nykyisen JSP:n uudelleen. Siksi ensimmäinen askel kohti web-sovelluksen kansainvälistämistä on määrittää URL-osoite näille attribuuteille, kuten esimerkissä H1 luetellaan:
Esimerkki H1. flags.jsp
Kunkin href
-attribuutin URL-osoite on sama: flags.do
. Tähän URL-osoitteeseen liitetään kaksi pyyntöparametria: yksi lippua vastaavalle lokaalille ja toinen, joka edustaa nykyisen JSP:n polkua. Jälkimmäinen request-parametri saadaan kutsumalla Http.ServletRequest.getServletPath()
-metodia.
Sovelluksen käyttöönottokuvauksessa kartoitin kaikki URL-osoitteet, jotka päättyvät .do
:iin, Strutsin action-servletille näin:
Esimerkki H2. WEB-INF/web.xml (Ote)
Huomautus: Katso artikkelistani ”Take Command of Your Software” (JavaWorld, kesäkuu 2002) lisätietoja Strutsista ja Strutsin action-servletistä.
Seuraavaksi kartoitin Strutsin konfigurointitiedostossa polun /flags
Strutsin actioniin actions.FlagAction
, joka on lueteltu esimerkissä H3:
Esimerkki H3. WEB-INF/struts-config.xml
Tämän kartoituksen ansiosta URL-osoite flags.do
saa Struts-toimintoservletin kutsumaan metodia actions.FlagAction.execute()
, joten lippua napsauttamalla kutsutaan metodi actions.FlagAction.execute()
. Esimerkissä H4 luetellaan actions.FlagAction
-luokka:
Esimerkki H4. WEB-INF/classes/actions/FlagAction.java
Metodi actions.FlagAction.execute()
hankkii viittauksen locale
-pyyntöparametriin ja välittää tämän arvon JSTL Config
-luokan set()
-metodille. Kyseinen metodi tallentaa lokaliteettia edustavan merkkijonon FMT_LOCALE
-konfiguraatioasetukseen, jota JSTL käyttää tekstin lokalisointiin ja numeroiden, valuuttojen, prosenttien ja päivämäärien muotoiluun.
Nyt kun olen määrittänyt lokaliteetin JSTL:n kansainvälistämistoimia varten, määrittelen seuraavaksi resurssinipun sovelluksen käyttöönottokuvaajaan, jonka ote on lueteltu esimerkissä H5:
Esimerkki H5. WEB-INF/web.xml (Ote)
Resurssinipun pohjanimi resources
on määritetty javax.servlet.jsp.jstl.fmt.localizationContext
context-initialization-parametrille. Tämä tarkoittaa, että JSTL etsii tiedostoa nimeltä resources_en.properties
, kun lokaaliksi on asetettu brittienglanti (en-GB
), ja resources_zh.properties
, kun lokaaliksi on asetettu kiina (zh-ZH
).
Nyt kun olen määrittänyt resurssinipun ja lokaalin JSTL:n kansainvälistämistoiminnoille, muokkaan seuraavaksi JSP-tiedostot käyttämään näitä toimintoja, kuten esimerkit H6-H9 osoittavat:
Esimerkki H7. header.jsp
Esimerkki H8. content.jsp
Esimerkeissä H6-H9 JSP:t käyttävät JSTL-toimintoa <fmt:message>
poimimaan Unicode-merkkijonot käyttöönoton kuvaajassa määritetystä resurssipaketista. Esimerkeissä H10 ja H11 luetellaan vastaavasti englannin- ja kiinankieliset resurssiniput:
Esimerkki H10. WEB-INF/classes/resources_en.properties
Esimerkki H11. WEB-INF/classes/resources_zh.properties
Sähköposti
Minulle lähettämässään sähköpostiviestissä Joseph Friedman kirjoitti:
Kirjoituksessa ”Decorate Your Java Code” (JavaWorld, joulukuu 2001) kirjoitat:
”Sisällyttävä objekti, joka tunnetaan nimellä decorator (koriste-olio), noudattaa sen objektin käyttöliittymää, jonka se sulkee sisäänsä, ja sen avulla koriste-oliota voidaan käyttää ikään kuin kyseessä olisi instanssi objektista, jonka se ympäröi.”
Koodiesimerkki kuitenkin koristaa
FileReader
:nLineNumberReader
:lla ja kutsuureadLine()
:tä, joka ei kuuluFileReader
:n rajapintaan; näin ollen et käytäLineNumberReader
:aa läpinäkyvästi.”
Kumpaakin FileReader
:aa ja LineNumberReader
:aa noudatetaan rajapinnan suhteen, jonka määrittelee Reader
-luokka, jota ne molemmat laajentavat. Ideana on, että voit välittää koristeen mille tahansa metodille, joka odottaa viittausta Reader
-luokkaan. Nämä metodit pysyvät autuaan tietämättöminä kyseisen koristeen erityisominaisuuksista – tässä tapauksessa kyvystä lukea tiedostoja ja tuottaa rivinumeroita. Jos kuitenkin tiedät noista erikoisominaisuuksista, voit hyödyntää niitä.
Se, että korostaja omaa (yhden tai useamman) metodin, joita koristetulta objektilta puuttuu, ei millään tavalla riko korostaja-mallin tarkoitusta; itse asiassa se on kyseisen mallin keskeinen piirre: lisätä toiminnallisuutta ajonaikaisesti objektiin korostaen objekteja rekursiivisesti.
Jos katsot Design Patterns -sivua 173, näet tämän:
Decorator-aliluokat voivat vapaasti lisätä operaatioita erityistä toiminnallisuutta varten. Esimerkiksi
ScrollDecorator
:nScrollTo
-operaatio antaa muiden objektien selata käyttöliittymää *jos* ne tietävät, että käyttöliittymässä sattuu olemaanScrollDecorator
-objekti.
DavidGeary on kirjoittanut teokset Core JSTL Mastering the JSP Standard TagLibrary (Core JSTL Mastering the JSP Standard TagLibrary), joka julkaistaan tänä syksynä Prentice-Hallin ja Sun Microsystems Pressin kustantamana, Advanced JavaServer Pages -teoksen (PrenticeHall, 2001; ISBN: 013030307041) ja Graphic Java -sarjan teoksen (Sun MicrosystemsPressin kustantama teos). David on kehittänyt oliosuuntautuneita ohjelmistoja lukuisilla oliosuuntautuneilla kielillä 18 vuoden ajan. Siitä lähtien, kun GOFDesign Patterns -kirja julkaistiin vuonna 1994, David on ollut aktiivinen suunnittelumallien kannattaja, ja hän on käyttänyt ja toteuttanut suunnittelumalleja Smalltalkissa, C++:ssa ja Javassa. Vuonna 1997 David alkoi työskennellä täysipäiväisesti kirjailijana ja satunnaisena puhujana ja konsulttina. David on jäsenenä asiantuntijaryhmissä, jotka määrittelevät JSP-standardin mukautetun tag-kirjaston ja JavaServer Facesin, ja hän osallistuu Apache Struts JSP-kehyksen kehittämiseen.