L'associazione di composizione

L'associazione di composizione è una relazione forte tra due classi.
Essa è un tipo di associazione tutto-parte (o tutto-parti), in cui una classe (detta classe tutto o contenitore) è composta, cioè possiede, una o più istanze di un'altra classe (detta classe parte o componente).

Il termine relazione forte sta ad indicare che gli oggetti della classe parte esistono solo in qualità di componenti dell'istanza della classe tutto e non possono esistere indipendentemente da essa e viceversa.

Se l'oggetto della classe tutto viene distrutto, anche tutte le istanze della classe parte possedute cessano di esistere.
In altri termini possiamo dire che la vita degli oggetti delle classi tutto e parte è fortemente legata ed essi possono esistere solo in quanto legati dall'associazione (non possono esistere in modo indipendente).

Questa associazione è nota anche come associazione HAS-A, in quanto gli oggetti della classe tutto hanno (possiedono) gli oggetti della classe parte.

Nei diagrammi UML, la composizione si rappresentata con una linea continua con un rombo pieno dalla parte della classe tutto.

Associazione UML di composizione

L'associazione può essere unidirezionale, ossia solo la classe tutto dipende dalla classe parte. In tal caso è presente anche una freccia a punta aperta dal lato della classe parte.

Associazione UML di composizione unidirezionale

Se la dipendenza è, invece, bidirezionale, non sono presenti frecce, come raffigurato nell'immagine seguente.

Associazione UML di composizione bidirezionale

Dai concetti sopra esposti si deduce che, necessariamente, la classe tutto deve dipendere dalla classe parte, in quanto, per forza di cose, deve avere uno o più attributi con funzione di contenitore delle istanze della classe parte.
Viceversa, la classe parte potrebbe non sapere di essere un componente della classe tutto, nel senso che potrebbe non avere nessun attributo che fa riferimento alla classe tutto a cui appartiene.
Ne consegue che è proprio questa caratteristica a determinare il tipo unidirezionale o bidirezionale dell'associazione.

Vediamo qualche esempio concreto per comprendere meglio.
Consideriamo il diagramma UML seguente:

Esempio di associazione UML di composizione, auto e telaio

Possiamo analizzare, da un punto di vista logico, il legame tra l'automobile ed il telaio ed concludere che l'automobile esiste in quanto composta dal telaio e, viceversa, il telaio è proprio dell'automobile e non può essere prelevato ed utilizzato su un'altra automobile.
Si tratta, quindi, di un legame forte, che giustifica una associazione di composizione.
Le vite dei due oggetti sono strettamente legate. Se si distrugge l'automobile, di conseguenza si distrugge il suo telaio e viceversa.
Tale conclusione conduce l'analista a produrre il diagramma raffigurato.
Inoltre, l'analista potrebbe decidere che l'automobile sia a conoscenza dell'esistenza del telaio (vedi attributo di tipo Telaio), ma non viceversa (la classe Telaio non presenta nessun attributo, o parametro di input/output di metodi di tipo Automobile).
Questo comporterebbe l'unidirezionalità dell'associazione.

Da un punto di vista tecnico, affinché sia rispettata la composizione, quindi il legame forte tra l'automobile ed il suo telaio, il programmatore, che implementerà il modello, dovrà fare in modo che l'istanza di Telaio sia creata internamente alla classe Automobile (nel costruttore o in altro metodo) e non fornita esternamente ad altri oggetti, attraverso parametri di output di metodi pubblici.

Notiamo, infatti, che il progettista non ha inserito nel modello il metodo getter pubblico dell'attributo Telaio (o, se lo inserisce per esigenze interne alla classe, ne imposta la visibilità privata), ma, allo scopo di permettere, eventualmente, agli utilizzatori di Automobile di conoscere il numero di telaio, ha progettato un apposito metodo (numeroTelaio) con il compito di restituire tale informazione.

Se, invece, il progettista avesse voluto che anche la classe Telaio fosse stata a conoscenza dell'automobile di appartenenza, allora l'associazione sarebbe stata bidirezionale, con le integrazioni illustrate di seguito.

Esempio di associazione UML di composizione, auto e telaio bidirezionale

Si noti la presenza dell'attributo e del parametro del costruttore, di tipo Automobile nella classe Telaio. In presenza di tale scelta del progettista, l'associazione deve, per forza di cose, essere bidirezionale, come evidenziato dall'assenza di frecce nella linea che unisce le due classi.