Intent
- Samenstellen van objecten in boomstructuren om hele hiërarchieën weer te geven. Composite laat clients individuele objecten en samenstellingen van objecten uniform behandelen.
- Recursieve compositie
- “Directories contain entries, each of which could be a directory.”
- 1-to-many “has a” up the “is a” hierarchy
Problem
Application needs to manipulate a hierarchical collection of “primitive “and “composite” objects. Het verwerken van een primitief object wordt op één manier afgehandeld, en het verwerken van een samengesteld object wordt op een andere manier afgehandeld. Het is niet wenselijk om het “type” van elk object op te vragen voordat je het probeert te verwerken.
Discussie
Definieer een abstracte basisklasse (Component) die het gedrag specificeert dat op uniforme wijze moet worden uitgeoefend op alle primitieve en samengestelde objecten. Onderklasseer de primitieve en samengestelde klassen van de Component-klasse. Elk Composite-object “koppelt” zichzelf alleen aan het abstracte type Component als het zijn “children” beheert.
Gebruik dit patroon wanneer u “composites hebt die componenten bevatten, waarvan elk een composite zou kunnen zijn”.
Child management methods zouden normaliter moeten worden gedefinieerd in de Composite-klasse. Helaas vereist de wens om Primitieven en Composieten uniform te behandelen dat de methoden worden verplaatst naar de abstracte Component-klasse. Zie het gedeelte “Adviezen” hieronder voor een discussie over “veiligheid” versus “transparantie”-aspecten.
Structuur
Composieten die Componenten bevatten, waarvan elk eenComposiet zou kunnen zijn.
Menu’s die menu-items bevatten, waarvan elk een menu zou kunnen zijn.
Rijkkolom-GUI-lay-outbeheerders die widgets bevatten, waarvan elk een rijkolom-GUI-lay-outbeheerder zou kunnen zijn.
Directories die bestanden bevatten, die elk een directory kunnen zijn.
Containers die elementen bevatten, die elk een container kunnen zijn.
Voorbeeld
De Composite stelt objecten samen in boomstructuren en laat clienten individuele objecten en samenstellingen uniform behandelen. Hoewel het voorbeeld abstract is, zijn rekenkundige expressies Composites. Een rekenkundige uitdrukking bestaat uit een operand, een operator (+ – * /),en een andere operand. De operand kan een getal zijn, of een andere rekenkundige uitdrukking. Zo zijn 2 + 3 en (2 + 3) + (4 * 6) beide geldige uitdrukkingen.
Check list
- Vergewis u ervan dat uw probleem gaat over het weergeven van “geheel-deel”-hiërarchische relaties.
- Overweeg de heuristiek, “Containers die containees bevatten, waarvan elk een container zou kunnen zijn.” Bijvoorbeeld, “Assemblages die componenten bevatten, die elk een assemblage kunnen zijn. “Verdeel uw domeinconcepten in containerklassen en containeklassen.
- Creëer een “kleinste gemene deler”-interface die uw containers en containees uitwisselbaar maakt. Deze moet het gedrag specificeren dat uniform moet worden uitgeoefend op alle containee- en containerobjecten.
- Alle container- en containeklassen verklaren een “is een”-relatie met de interface.
- Alle containerklassen verklaren een één-op-veel “heeft een”-relatie met de interface.
- Containerklassen maken gebruik van polymorfisme om te delegeren naar hun containeeobjecten.
- De methoden voor het beheer van kinderen moeten normaal gesproken worden gedefinieerd in de Composite-klasse. Helaas kan de wens om blad- en composietobjecten uniform te behandelen vereisen dat de methoden worden gepromoveerd naar de abstracte Component-klasse. Zie de Gang of Four voor een discussie over deze afweging tussen “veiligheid” en “transparantie”.
Vuistregels
- Composite en Decorator hebben vergelijkbare structuurdiagrammen, die het feit weerspiegelen dat beide berusten op recursieve samenstelling om een onbepaald aantal objecten te organiseren.
- Composite kan worden doorkruist met Iterator. Bezoeker kan een bewerking toepassen op een composiet. Een composiet kan Chain of Responsibility gebruiken om componenten via hun ouder toegang te geven tot globale eigenschappen. Het kan ook Decorator gebruiken om deze eigenschappen te overschrijven op onderdelen van de compositie. Het zou Observer kunnen gebruiken om de ene objectstructuur aan de andere te koppelen en State om een component zijn gedrag te laten veranderen als zijn toestand verandert.
- Composite kan je een Mediator laten samenstellen uit kleinere stukjes door middel van recursieve compositie.
- Decorator is ontworpen om je verantwoordelijkheden aan objecten toe te laten voegen zonder te hoeven subklassen. Composite’s focus ligt niet op verfraaiing maar op representatie. Deze intenties zijn verschillend, maar complementair.Daarom worden Composite en Decorator vaak in combinatie gebruikt.
- Flyweight wordt vaak gecombineerd met Composite om gedeelde leafnodes te implementeren.
Opinions
Het hele punt van het Composite pattern is dat de Composite atomair kan worden gebruikt, net als een leaf. Als je een Iterator-protocol wilt aanbieden, prima, maar ik denk dat dat buiten het patroon zelf valt. De kern van dit patroon is de mogelijkheid voor een client om operaties op een object uit te voeren zonder te hoeven weten dat er vele objecten in zitten.
Om een heterogene verzameling van objecten atomair (of transparant) te kunnen behandelen, moet de “child management” interface worden gedefinieerd aan de basis van de Composite class hiërarchie (de abstracteComponent class). Deze keuze kost je echter veiligheid, omdat clienten kunnen proberen om zinloze dingen te doen zoals objecten toevoegen en verwijderen uit leaf objecten. Aan de andere kant, als je “ontwerpt voor veiligheid”, wordt de interface voor het beheer van het kind gedeclareerd in de Composite klasse, en verlies je transparantie omdat bladeren en Composites nu verschillende interfaces hebben.
Smalltalk implementaties van het Composite patroon hebben gewoonlijk de interface voor het beheer van de componenten niet in de Component interface, maar in de Composite interface. C++ implementaties hebben de neiging om het in de Component interface te plaatsen. Dit is een buitengewoon interessant feit, en een waar ik vaak over nadenk. Ik kan theorieën aandragen om het te verklaren, maar niemand weet zeker waarom het waar is.
Mijn Component classes weten niet dat Composites bestaan. Ze bieden geen hulp bij het navigeren door Composites, noch bij het wijzigen van de inhoud van een Composite. Dit is omdat ik wil dat de basisklasse (en al haar afgeleiden) herbruikbaar zijn in contexten die geen Composites vereisen. Wanneer ik een base class pointer krijg, en ik moet absoluut weten of het een Composite is of niet, dan zal ik dynamic_cast
gebruiken om dit uit te zoeken. In die gevallen waarin dynamic_cast
te duur is, zal ik een Visitor gebruiken.
Algemene klacht: “Als ik de Composite interface in deComposite klasse duw, hoe ga ik dan een complexe structuur opsommen (d.w.z. doorkruisen)?” Mijn antwoord is dat wanneer ik gedragingen heb die van toepassing zijn op hiërarchieën zoals voorgesteld in het Composite patroon, ik typisch de Visitor gebruik, zodat opsomming geen probleem is – de Visit weet in elk geval precies met welk soort object hij te maken heeft. De Visititor hoeft niet elk object te voorzien van een opsomming-interface.
Composite dwingt je niet om alle Componenten als Composites te behandelen. Het vertelt je alleen om alle operaties die je “uniform” wilt behandelen in de Component klasse te zetten. Als add, remove, en soortgelijke operaties niet uniform behandeld kunnen, of mogen worden, plaats ze dan niet in de Component basisklasse. Bedenk overigens dat het structuurdiagram van elk patroon het patroon niet definieert; het geeft slechts weer wat in onze ervaring een gebruikelijke realisatie ervan is. Alleen omdat Composite’s structure diagram child management operaties laat zien in de Component base class, wil dat nog niet zeggen dat alle implementaties van het patroon hetzelfde moeten doen.
Steun onze gratis website en bezit het eBook!
- 22 design patterns en 8 principes diepgaand uitgelegd
- 406 goed gestructureerde, makkelijk te lezen, jargon-vrije pagina’s
- 228 duidelijke en behulpzame illustraties en diagrammen
- Een archief met code voorbeelden in 4 talen
- Alle apparaten ondersteund: EPUB/MOBI/PDF formaten
Meer informatie…