Ohjelmointi

Katsaus komposiittimalliin

Eräänä päivänä kuuntelin kansallista julkista radiota Autopuhelu, suosittu viikoittainen lähetys, jonka aikana soittajat esittävät kysymyksiä ajoneuvoistaan. Ennen jokaista ohjelmataukoa näyttelyn isännät pyytävät soittajia soittamaan numeroon 1-800-CAR-TALK, joka vastaa numeroa 1-800-227-8255. Ensimmäiset osoittautuvat tietysti paljon helpommin muistettaviksi kuin jälkimmäiset, osittain siksi, että sanat "AUTOPALVELU" ovat yhdistelmä: kaksi sanaa, jotka edustavat seitsemää numeroa. Ihmisten on yleensä helpompaa käsitellä komposiitteja kuin niiden yksittäisiä komponentteja. Samoin kun kehität olio-ohjelmistoa, on usein kätevää käsitellä komposiitteja samalla tavalla kuin yksittäisiä komponentteja. Tämä lähtökohta edustaa Composite-suunnittelumallin perusperiaatetta, tämän aihetta Java-suunnittelumallit erä.

Komposiittikuvio

Ennen kuin sukellamme komposiittikuvioon, minun on ensin määriteltävä yhdistelmäesineet: esineet, jotka sisältävät muita esineitä; esimerkiksi piirustus voi koostua graafisista primitiivistä, kuten viivoista, ympyröistä, suorakulmioista, tekstistä ja niin edelleen.

Java-kehittäjät tarvitsevat komposiittikuvion, koska meidän on usein manipuloitava komposiitteja täsmälleen samalla tavalla kuin primitiivisiä objekteja. Esimerkiksi graafiset primitiivit, kuten viivat tai teksti, on piirrettävä, siirrettävä ja muutettava kokoa. Mutta haluamme suorittaa saman toiminnan myös komposiiteilla, kuten piirustuksilla, jotka koostuvat näistä primitiivistä. Ihannetapauksessa haluaisimme suorittaa operaatioita sekä primitiivisille esineille että komposiiteille täsmälleen samalla tavalla, tekemättä eroa näiden kahden välillä. Jos meidän on tehtävä ero primitiivisten esineiden ja komposiittien välillä, jotta voimme suorittaa samat toiminnot näille kahdelle objektityypille, koodistamme tulee monimutkaisempi ja sitä on vaikea toteuttaa, ylläpitää ja laajentaa.

Sisään Suunnittelumalleja, kirjoittajat kuvaavat yhdistelmämallia näin:

Sommittele objektit puurakenteiksi edustamaan osa-kokonais-hierarkioita. Composite antaa asiakkaiden kohdella yksittäisiä esineitä ja esineiden koostumuksia yhdenmukaisesti.

Komposiittimallin toteuttaminen on helppoa. Yhdistelmäluokat laajentavat primitiivisiä objekteja edustavaa perusluokkaa. Kuvassa 1 on luokkakaavio, joka kuvaa yhdistelmäkuvion rakennetta.

Kuvan 1 luokkakaaviossa käytin luokan nimiä Suunnittelumalli's Komposiittikuvakeskustelu: Komponentti edustaa primitiivisten objektien perusluokkaa (tai mahdollisesti käyttöliittymää) ja Komposiitti edustaa yhdistelmäluokkaa. Esimerkiksi Komponentti luokka saattaa edustaa graafisten primitiivien perusluokkaa, kun taas Komposiitti luokka saattaa edustaa a Piirustus luokassa. Kuva 1 Puun lehti luokka edustaa konkreettista primitiivistä esinettä; esimerkiksi a Linja luokka tai a Teksti luokassa. Käyttö1 () ja Käyttö2 () menetelmät edustavat toimialakohtaisia ​​menetelmiä, jotka molemmat ovat toteuttaneet Komponentti ja Komposiitti luokat.

Komposiitti luokka ylläpitää kokoelmaa komponentteja. Tyypillisesti, Komposiitti menetelmät toteutetaan iteroimalla kokoelma ja kutsumalla kullekin sopiva menetelmä Komponentti kokoelmassa. Esimerkiksi a Piirustus luokka saattaa toteuttaa sen piirtää () tällainen menetelmä:

// Tämä menetelmä on yhdistelmämenetelmä public void draw () {// Toista komponentit (int i = 0; i <getComponentCount (); ++ i) {// Hanki viittaus komponenttiin ja kutsu sen piirtäminen menetelmä Komponenttikomponentti = getComponent (i); komponentti.piirrä (); }} 

Jokaiselle järjestelmässä toteutetulle menetelmälle Komponentti luokka, Komposiitti luokka toteuttaa menetelmän samalla allekirjoituksella, joka toistaa komposiitin komponentit, kuten piirtää () edellä lueteltu menetelmä.

Komposiitti luokka laajentaa Komponentti luokka, joten voit välittää komposiitin menetelmälle, joka odottaa komponenttia; Harkitse esimerkiksi seuraavaa menetelmää:

// Tämä menetelmä toteutetaan luokassa, joka ei liity // komponentti- ja yhdistelmäluokkiin public void repaint (komponenttikomponentti) {// Komponentti voi olla komposiitti, mutta koska se ulottuu // komponenttiluokkaan, tämän menetelmän ei tarvitse olla // erottaa komponentit ja komposiitit komponentti.draw (); } 

Edelliselle menetelmälle siirretään komponentti - joko yksinkertainen komponentti tai komposiitti - ja sitten se käynnistää kyseisen komponentin piirtää () menetelmä. Koska Komposiitti luokka jatkuu Komponentti, maalata uudelleen () menetelmän ei tarvitse tehdä eroa komponenttien ja komposiittien välillä - se yksinkertaisesti vetoaa piirtää () menetelmä komponentille (tai komposiitille).

Kuvan 1 komposiittimalliluokkakaavio havainnollistaa yhtä ongelmaa kuviossa: sinun on tehtävä ero komponenttien ja komposiittien välillä viitattaessa Komponentti, ja sinun on käytettävä yhdistelmäkohtaista menetelmää, kuten addComponent (). Täytät tavallisesti tämän vaatimuksen lisäämällä menetelmän, kuten isComposite (), Komponentti luokassa. Tämä menetelmä palaa väärä komponenttien osalta ja se ohitetaan Komposiitti luokan palata totta. Lisäksi sinun on myös heitettävä Komponentti viittaus a Komposiitti esimerkiksi näin:

... if (komponentti.isKomposiitti ()) {Komposiittikomposiitti = (Komposiitti) komponentti; composite.addComponent (someComponentThatCouldBeAComposite); } ... 

Huomaa, että addComponent () menetelmä on läpäissyt a Komponentti viite, joka voi olla joko primitiivinen komponentti tai komposiitti. Koska kyseinen komponentti voi olla komposiitti, voit sommitella komponentit puurakenteeseen, kuten yllä mainittu lainaus osoittaa Suunnittelumalleja.

Kuvassa 2 on esitetty vaihtoehtoinen komposiittikuviototeutus.

Jos toteutat kuvan 2 komposiittikuvion, sinun ei tarvitse koskaan tehdä eroa komponenttien ja komposiittien välillä, eikä sinun tarvitse heittää Komponentti viittaus a Komposiitti ilmentymä. Joten yllä lueteltu koodiosa pienenee yhdeksi riviksi:

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

Mutta jos Komponentti viittaus edelliseen koodipalaan ei viittaa a Komposiitti, mitä pitäisi addComponent () tehdä? Se on tärkeä kiistakuva kuvion 2 Composite-mallin toteutuksessa. Koska primitiiviset komponentit eivät sisällä muita komponentteja, komponentin lisääminen toiseen komponenttiin ei ole järkevää, joten Component.addComponent () menetelmä voi joko epäonnistua hiljaa tai heittää poikkeuksen. Tyypillisesti komponentin lisääminen toiseen primitiiviseen komponenttiin katsotaan virheeksi, joten poikkeuksen heittäminen on ehkä paras toimintatapa.

Joten mikä yhdistetyn mallin toteutus - kuvassa 1 tai kuvassa 2 - toimii parhaiten? Se on aina suuren keskustelun aihe Composite-mallin toteuttajien keskuudessa; Suunnittelumalleja pitää parempana kuvan 2 toteutusta, koska sinun ei tarvitse koskaan tehdä eroa komponenttien ja säiliöiden välillä, eikä sinun tarvitse koskaan suorittaa valua. Henkilökohtaisesti pidän parempana kuvan 1 toteutuksesta, koska minulla on voimakas vastenmielisyys sellaisten luokan menetelmien toteuttamiseen, joilla ei ole merkitystä kyseiselle objektityypille.

Nyt kun ymmärrät komposiittimallin ja kuinka voit toteuttaa sen, tutkitaan komposiittimalliesimerkki Apache Struts JavaServer Pages (JSP) -kehyksellä.

Komposiittikuvio ja tukijalat

Apache Struts -kehys sisältää JSP-tunnuskirjaston, joka tunnetaan nimellä ruudut, jonka avulla voit luoda verkkosivun useista JSP: stä. Ruudut on itse asiassa J2EE (Java 2 Platform, Enterprise Edition) CompositeView -mallin toteutus, joka perustuu itse Suunnittelumalleja Komposiittikuvio. Ennen kuin keskustelemme yhdistelmäkuvion merkityksestä laatatunnistekirjastoon, tarkistetaan ensin laatat ja niiden käyttö. Jos olet jo perehtynyt tukiruutuihin, voit ohittaa seuraavat kohdat ja aloittaa lukemisen kohdasta "Käytä yhdistelmäkuviota tukiruutujen kanssa".

merkintä: Voit lukea lisää J2EE CompositeView -mallista kohdasta "Web-sovelluksen komponentit, jotka on helppo tehdä komposiittinäkymällä" (JavaWorld, Joulukuu 2001) artikkeli.

Suunnittelijat rakentavat usein verkkosivuja joukolla erillisiä alueita; esimerkiksi kuvion 3 verkkosivusto käsittää sivupalkin, otsikon, sisältöalueen ja alatunnisteen.

Verkkosivustot sisältävät usein useita verkkosivuja, joilla on identtiset asettelut, kuten kuvan 3 sivupalkki / otsikko / sisältö / alatunniste. Struts-ruutujen avulla voit käyttää sekä sisältöä että asettelua uudelleen useilla verkkosivuilla. Ennen kuin keskustelemme uudelleenkäytöstä, katsotaanpa, kuinka kuvan 3 asettelu toteutetaan perinteisesti pelkällä HTML: llä.

Toteuta monimutkaiset asettelut käsin

Esimerkki 1 osoittaa, kuinka voit toteuttaa kuvion 3 verkkosivun HTML-koodilla:

Esimerkki 1. Monimutkainen asettelu, joka toteutetaan käsin

    Monimutkaisten asettelujen toteuttaminen käsin <% - Yksi taulukko näyttää kaiken tämän sivun sisällön -%>
Linkit

Koti

Tuotteet

Lataukset

valkoiset paperit

Ota meihin yhteyttä

Tervetuloa Sabreware, Inc.:yn
Sivukohtainen sisältö menee tänne

Kiitos käynnistä!

Edellisellä JSP: llä on kaksi suurta haittapuolta: Ensinnäkin sivun sisältö on upotettu JSP: hen, joten et voi käyttää mitään niistä uudelleen, vaikka sivupalkki, otsikko ja alatunniste ovat todennäköisesti samat useilla verkkosivuilla. Toiseksi sivun asettelu on upotettu myös JSP: hen, joten et myöskään voi käyttää sitä uudelleen, vaikka monet muut saman verkkosivuston verkkosivut käyttävät samaa asettelua. Voimme käyttää toimet ensimmäisen haitan korjaamiseksi, kuten keskustelen seuraavaksi.

Toteuta monimutkaiset asettelut JSP: n kanssa

Esimerkki 2 esittää kuvion 3 verkkosivun toteutuksen, joka käyttää :