Design Pattern in Java: Composite

Analizziamo Composite, un pattern di partizionamento che ci permette di gestire le classi in una struttura ad albero

Pattern Composite

Nello sviluppo di software che utilizza un linguaggio Object Oriented, come Java, può succedere di trovarsi di fronte alla necessità di gestire gerarchie di oggetti, all’interno delle quali possiamo trovare oggetti semplici e altri che fanno da contenitore ad oggetti più complessi. L’esempio classico per capire bene questo pattern è quello relativo alle classi grafiche. Da questo punto di vista possiamo avere classi che rappresentano concetti semplici come il segmento, la circonferenza e quant’altro.

Le classi complesse in questo caso possono essere quelle che non fanno altro che comporre più classi semplici al loro interno, includendole per disegnare qualcosa di più complesso della semplice figura geometrica. Dal punto di vista dell’utilizzatore però, gestire in maniera diversa queste classi può portare ad una disorganizzazione del codice e soprattutto ad un’entropia ingiustificata.

Proprio per questo possiamo gestire in maniera migliore queste gerarchie di classi utilizzando il pattern Composite. Nella seguente immagine viene mostrata la classica relazione che questo pattern introduce

Design Pattern Composite

 

Praticamente noi andiamo a definire una classe astratta, Component, dove vengono definiti i metodi che devono essere mostrati al client. Questo deve sapere soltanto che per visualizzare ad esempio un certo oggetto grafico dovrà richiamare un certo metodo, senza preoccuparsi di tutta la gerarchia di classi incluse nel componente.

L’oggetto semplice, che in questo caso viene chiamato Leaf (foglia in inglese) sarà quello che effettivamente realizza l’operazione mentre l’oggetto Composite sarà quello che gestirà tutta la gerarchia di oggetti contenuti richiamando ogni volta l’operazione su uno dei suoi oggetti-figli. Praticamente la gestione della gerarchia è simile a quella di un albero, all’interno del quale possiamo avere delle foglie (Leaf) sulle quali viene direttamente invocato il metodo e dei Composite (nodi) che al loro interno possono avere rispettivamente altri Composite e/o altre foglie

Un esempio pratico

Passiamo ora ad un esempio per chiarire il funzionamento di questo pattern. Creiamo prima di tutto la classe astratta Component

All’interno abbiamo definito i metodi add e remove che servono per aggiungere/rimuovere componenti e infine il metodo stampaInfo che sarà quello che effettivamente svolgerà il compito richiesto dal client. Passiamo ora al Leaf, ovvero la classe foglia

Questa classe implementa correttamente il metodo di “business” stampaInfo mentre per quanto riguarda gli altri due metodi, viene lanciata un Exception, perchè giustamente quelle non sono operazioni che possono essere fatte su un nodo foglia della nostra gerarchia. Vediamo quindi la classe Composite

In Composite abbiamo utilizzato un Vector per gestire tutti nodi sottostanti e nel momento in cui viene richiamato stampaInfo, vengono richiamati in sequenza tutti i metodi stampaInfo degli oggetti “foglia”. Chiaramente se l’oggetto è a sua volta un Composite, verrà richiamato ricorsivamente il metodo fino a quando non si arriva alle foglie Leaf. Per testare questo semplice esempio è possibile utilizzare la seguente classe

In questo esempio abbiamo cercato di rappresentare la seguente struttura ad albero

Design Pattern Composite 2

Nel momento in cui andiamo ad invocare il metodo stampaInfo(), l’oggetto Composite “root” avrà il compito di andare a richiamare questo metodo in tutti gli oggetti ad esso collegati. Per migliorare il nostro esempio potevamo creare diverse tipologie di foglie, che estendevano tutte la classe astratta Component ed altre classi Composite. In questo modo avremmo potuto differenziare il comportamento del metodo stampaInfo nelle diverse classi, gestendo comunque tutto in maniera più semplice dal punto di vista del client.

Composite pattern su Wikipedia
Composite View, pattern derivato dal Composite

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *