Comporre oggetti in strutture ad albero per rappresentare gerarchie parte-tutto, permettendo ai client di trattare oggetti singoli e composizioni di oggetti in modo uniforme.
Per creare diagrammi complessi a partire da componenti semplici e raggrupparli ricorsivamente.
Per semplificare il codice, evitando di distinguere tra oggetti primitivi e contenitori.
Per consentire la gestione uniforme di oggetti primitivi e compositi.
Quando vuoi rappresentare gerarchie parte-tutto di oggetti.
Quando i client devono ignorare la differenza tra oggetti singoli e composizioni di oggetti.
Quando i client devono trattare uniformemente gli oggetti nella struttura composita.
Component (Graphic):
Dichiara l'interfaccia per tutti gli oggetti nella composizione.
Implementa un comportamento predefinito per l'interfaccia comune.
Leaf (Rectangle, Line, Text, ecc.):
Rappresenta oggetti foglia senza figli.
Definisce il comportamento per gli oggetti primitivi.
Composite (Picture):
Contiene altri componenti, inclusi Leaf e Composite.
Implementa operazioni per gestire i figli.
Client:
Usa l'interfaccia Component per interagire con gli oggetti.
Il client interagisce con la struttura composita tramite l'interfaccia Component.
Se il destinatario è un Leaf, gestisce direttamente la richiesta.
Se il destinatario è un Composite, inoltra la richiesta ai suoi figli, eseguendo eventualmente operazioni aggiuntive.
Vantaggi:
Gerarchie parte-tutto: Gli oggetti primitivi possono essere composti ricorsivamente.
Semplificazione del client: I client trattano uniformemente oggetti singoli e compositi.
Estensibilità: È facile aggiungere nuovi tipi di componenti senza modificare il client.
Svantaggi:
Il design può diventare troppo generico, rendendo difficile imporre restrizioni sui componenti di un Composite.
Potrebbe essere necessario usare controlli a runtime per garantire vincoli.
Riferimenti espliciti ai genitori: Semplificano la navigazione e la gestione, ma richiedono coerenza nella struttura.
Condivisione dei componenti: Riduce l'uso di memoria ma può causare ambiguità.
Massimizzare l'interfaccia Component: Consente ai client di essere indipendenti dalle classi specifiche, ma potrebbe violare il principio di progettazione gerarchica.
Operazioni sui figli:
Definirle in Component migliora la trasparenza ma riduce la sicurezza.
Definirle in Composite aumenta la sicurezza ma riduce la trasparenza.
Ordinamento dei figli: Usare il pattern Iterator per attraversare strutture ordinate.
Caching: Migliora le prestazioni, specialmente per traversamenti frequenti.
Eliminazione dei componenti: In assenza di garbage collection, il Composite dovrebbe eliminare i suoi figli.
Strutture dati: Scegliere la più adatta tra liste, alberi, array o tabelle hash, in base all'efficienza desiderata.
In molte applicazioni che richiedono la gestione di gerarchie parte-tutto, come editor grafici e sistemi di gestione dei documenti.
Iterator: Per attraversare i componenti in un ordine specifico.
Flyweight: Per condividere oggetti tra diverse composizioni.
Decorator: Per aggiungere responsabilità ai componenti.
Visitor: Per definire nuove operazioni su strutture composite.