Intent
- Objektien kokoaminen puurakenteiksi kokonaisten parthierarkioiden esittämiseksi. Komposiitin avulla asiakkaat voivat käsitellä yksittäisiä objekteja jaobjektien koosteita yhdenmukaisesti.
- Rekursiivinen kompositio
- ”Hakemistot sisältävät merkintöjä, joista jokainen voi olla hakemisto.”
- 1-monesta ”on a” ylöspäin ”on a” hierarkiassa
Ongelma
Sovelluksen täytyy käsitellä hierarkkista kokoelmaa ”primitiivisiä ”ja ”komposiittisia” objekteja. Primitiivisen objektin käsittely hoidetaan yhdellä tavalla, ja komposiittiobjektin käsittely hoidetaan eri tavalla.Jokaisen objektin ”tyypin” kysyminen ennen käsittelyä ei ole toivottavaa.
Keskustelu
Määritellään abstrakti perusluokka (Komponentti), joka määrittelee käyttäytymisen, jota on harjoitettava yhdenmukaisesti kaikissa primitiivisissä ja komposiittiobjekteissa. Luokittele Primitive- ja Composite-luokat Component-luokan alaluokiksi. Kukin Composite-objekti ”kytkeytyy” vain abstraktiin Component-tyyppiin, kun se hallitsee ”lapsiaan”.
Käytä tätä mallia aina, kun sinulla on ”komposiitteja, jotka sisältävät komponentteja, joista jokainen voi olla komposiitti”.
Lastenhallintamenetelmät tulisi normaalisti määritellä Composite-luokassa. Valitettavasti halu kohdella primitiivejä ja komposiitteja yhdenmukaisesti edellyttää, että nämä metodit siirretään abstraktiin Component-luokkaan. Katso ”Turvallisuus” vs. ”läpinäkyvyys”-kysymyksiä koskeva keskustelu alla olevasta ”Mielipiteet”-osiosta.
Rakenne
Komposiitit, jotka sisältävät Komponentteja, joista kukin voi olla Komposiitti.
Valikot, jotka sisältävät valikkokohteita, joista kukin voi olla valikko.
Rivi- ja sarakesarakkeiset graafisen käyttöliittymän asettelunhallintaohjelmat, jotka sisältävät widgetejä, joista kukin voisivatkin ollaryhmäsarakkeinen graafisen käyttöliittymän asettelunhallintaohjelma.
Kansiot, jotka sisältävät tiedostoja, joista kukin voi olla hakemisto.
Kontit, jotka sisältävät elementtejä, joista kukin voi olla kontti.
Esimerkki
Komposiitti kokoaa objekteja puurakenteiksi ja antaa asiakkaan käsitellä yksittäisiä objekteja ja koosteita yhtenäisesti. Vaikka esimerkki on abstrakti, aritmeettiset lausekkeet ovat Komposiitteja. Aritmeettinen lauseke koostuu operandista, operaattorista (+ – * /) ja toisesta operandista. Operandi voi olla luku tai muu aritmeettinen lauseke. Siten 2 + 3 ja (2 + 3) + (4 * 6) ovat molemmatvalideja lausekkeita.
Tarkistuslista
- Varmista, että ongelmassasi on kyse ”koko-osien ”hierarkkisten suhteiden esittämisestä.
- Harkitse heuristiikkaa: ”Kontit, jotka sisältävät kontakteja,joista jokainen voi olla kontti”. Esimerkiksi: ”Kokoonpanot, jotka sisältävät komponentteja, joista kukin voi olla kokoonpano.” Jaa toimialueen käsitteesi konttiluokkiin ja kontaktiluokkiin.
- Luo ”pienimmän yhteisen nimittäjän” rajapinta, joka tekee konttiluokista ja kontakteista keskenään vaihdettavia. Sen tulisi määritellä käyttäytyminen, jota on käytettävä yhdenmukaisesti kaikissa kontti- ja konttiobjekteissa.
- Kaikki kontti- ja konttiiniluokat ilmoittavat ”is a”-suhteen rajapintaan.
- Kaikki kontti-luokat ilmoittavat yksi-moneen ”has a”-suhteen rajapintaan.
- Kontti-luokat käyttävät polymorfismia delegoidaakseen konttiiniobjektejaan.
- Lastenhallintamenetelmät tulisi normaalisti määritellä komposiittiluokassa. Valitettavasti halu kohdella Leaf- ja Composite-objekteja yhdenmukaisesti saattaa vaatia, että metodit siirretään abstraktiin Component-luokkaan. Katso Gang of Four -teoksessa keskustelua näistä ”turvallisuuden” ja ”läpinäkyvyyden” välisistä kompromisseista.
Nyrkkisääntöjä
- Composite- ja Decorator-luokilla on samankaltaiset rakennekaaviot, jotka heijastavat sitä, että kumpikin luottaa rekursiiviseen sommitteluun organisoidakseen avointa määrää objekteja.
- Composite-luokkaa voidaan läpikäydä Iterator-luokan avulla. Visitor voi soveltaa operaatiota kompositioon. Komposiitti voisi käyttää Chain ofResponsibilityä, jotta komponentit pääsisivät käsiksi globaaleihin ominaisuuksiin vanhempiensa kautta. Se voisi myös käyttää Decoratoria näiden ominaisuuksien ohittamiseen koostumuksen osilla. Se voisi käyttää Observeriä sitoakseen yhden objektirakenteen toiseen ja Statea antaakseen komponentin muuttaa käyttäytymistään, kun sen tila muuttuu.
- Composite voi antaa sinun koostaa Mediatorin pienemmistä palasista rekursiivisen koostamisen avulla.
- Decorator on suunniteltu lisäämään vastuualueita objekteihin ilman alaluokittelua. Composite ei keskity ehostamiseen vaan esittämiseen. Nämä tarkoitukset ovat erillisiä, mutta täydentävät toisiaan.Näin ollen Compositea ja Decoratoria käytetään usein yhdessä.
- Flyweight yhdistetään usein Compositeen toteutettaessa jaettuja lehtisolmuja.
Opinions
Composite-mallin koko pointti on se, että Compositea voidaan käsitellä atomisesti, aivan kuten lehteä. Jos haluat tarjotaIteraattoriprotokollan, hyvä, mutta mielestäni se on kuvion itsensä ulkopuolella. Tämän mallin ytimessä on asiakkaan kyky suorittaa operaatioita objektille ilman, että sen tarvitsee tietää, että sen sisällä on monia objekteja.
Kyky käsitellä heterogeenista kokoelmaa objekteja atomisesti (tai läpinäkyvästi) edellyttää, että ”lastenhallinta”-rajapinta määritellään Composite-luokkahierarkian juuressa (abstraktiComponent-luokka). Tämä valinta maksaa kuitenkin turvallisuuden, koska asiakkaat voivat yrittää tehdä merkityksettömiä asioita, kuten lisätä ja poistaa objekteja lehtien objekteista. Toisaalta, jos ”suunnittelet turvallisuutta varten”, lasten hallintarajapinta ilmoitetaan Composite-luokassa, ja menetät läpinäkyvyyden, koska lehdillä ja Compositeilla on nyt eri rajapinnat.
Smalltalkin Composite-mallin toteutuksissa komponenttien hallintarajapinta ei yleensä ole Component-rajapinnassa, vaan Composite-rajapinnassa. C++-toteutukset asettavat sen yleensä Component-rajapintaan. Tämä on erittäin mielenkiintoinen seikka, jota pohdin usein. Voin tarjota teorioita sen selittämiseksi, mutta kukaan ei tiedä varmasti, miksi se on totta.
Komponenttiluokkani eivät tiedä, että komposiitteja on olemassa. Ne eivät tarjoa apua komposiittien navigointiin, eivätkä apua komposiitin sisällön muuttamiseen. Tämä johtuu siitä, että haluaisin perusluokan (ja kaikkien sen johdannaisten) olevan uudelleenkäytettävissä yhteyksissä, jotka eivät vaadi Komposiitteja. Kun minulle annetaan perusluokan osoitin, jos minun on ehdottomasti tiedettävä, onko se komposiitti vai ei, käytän dynamic_cast
saadakseni sen selville. Niissä tapauksissa, joissa dynamic_cast
on liian kallis, käytän Visitoria.
Yleinen valitus: ”Jos työnnän Composite-rajapinnan alaspäinComposite-luokkaan, miten voin luetella (eli läpikäydä) monimutkaisen rakenteen?” Vastaukseni on, että kun minulla on käyttäytymismalleja, jotka soveltavat Composite-mallissa esitetyn kaltaisia hierarkioita, käytän tyypillisesti Visitoria, joten luetteleminen ei ole ongelma – Visitork tietää kussakin tapauksessa tarkalleen, millaisen objektin kanssa se on tekemisissä. Vierailijan ei tarvitse tarjota jokaiselle objektille luettelorajapintaa.
Composite ei pakota kohtelemaan kaikkia komponentteja Compositeina. Se vain kehottaa sinua laittamaan kaikki operaatiot, joita haluat käsitellä ”yhtenäisesti”, Component-luokkaan. Jos lisäys-, poisto- ja vastaavia operaatioita ei voi tai saa käsitellä yhdenmukaisesti, älä laita niitä Component-perusluokkaan. Muista muuten, että kunkin mallin rakennekaavio ei määrittele mallia, vaan ainoastaan kuvaa sen kokemuksemme mukaan yleistä toteutusta. Se, että Compositen rakennekaavio näyttää lastenhallintaoperaatiot Component-perusluokassa, ei tarkoita, että kaikkien mallin toteutusten on tehtävä samoin.
Tukekaa ilmaista verkkosivustoamme ja omistakaa e-kirja!
- 22 suunnittelumallia ja 8 periaatetta syvällisesti selitettynä
- 406 hyvin jäsenneltyä, helppolukuista ja jargonista vapaata sivua
- 228 selkeää ja hyödyllistä kuvitusta ja kaaviota
- Arkisto, jossa on koodiesimerkkejä neljällä kielellä
- Kaikki laitteet tuettuina: Kaikki laitteet: EPUB/MOBI/PDF-formaatit
Lue lisää…