Composite

Il Design Pattern Composite è un pattern strutturale sviluppato al fine di consentire ad un client di trattare un gruppo di oggetti distinti come se fossero l’istanza di un singolo oggetto. Il pattern composite organizza gli oggetti in una struttura ad albero all’interno della quale i nodi rappresentano gli oggetti composti e le foglie gli oggetti semplici. Questo pattern viene utilizzato per dare la possibilità al client di manipolare oggetti singoli o composizioni in modo uniforme.

All’interno dello schema UML la classe astratta Component può tal volta essere rimpiazzata da una interfaccia Component.

Nella realizzazione del pattern si procede con la creazione di un oggetto generico in grado di rappresentare sia gli oggetti singoli (Leaf), che le loro composizioni (Composite), questo oggetto viene rappresentato dalla classe astratta Component. Gli oggetti composti (Composite) potranno poi aggregare oggetti di tipo semplice (o di tipo composto), in modo tale da rendere sempre possibile l’aggiunta di nuovi oggetti al gruppo. La classe astratta Component può essere arricchita con l’aggiunta di un metodo getChild in grado di restituire un oggetto di tipo Leaf, oppure di tipo Composite (a seconda del caso) correttamente castato.

Utilizzando il pattern composite il client può interfacciarsi con gli oggetti della classe Component senza necessariamente sapere se sta interagendo con un oggetto singolo (Leaf) o con un oggetto composito (Composite).

Composite in Java

Il seguente esempio scritto in linguaggio Java illustra come il pattern Composite possa essere utilizzato, ad esempio, per implementare una semplice classe grafica in grado di rappresentare un ellisse o una composizione di quest’ultimi.

import java.util.List;
import java.util.ArrayList;

interface Drawing {
  public void print(); // stampa la figura
}

/* oggetto singolo (leaf) */
class Ellipse implements Drawing {
  public void print() {
    System.out.println("Ellipse"); // stampa la figura elisse
  }
}

/* oggetto aggregato (Composite) */
class CompositeDrawing implements Drawing {
  private List<Drawing> listDrawing = new ArrayList<Drawing>(); // collezione di grafici

  /* stampa tutte le figure */
  public void print() {
    for (Drawing drawing: listDrawing) {
      drawing.print();
    }
  }

  /* aggiunge la figura alla composizione */
  public void add(Drawing drawing) {
    listDrawing.add(drawing);
  }

  /* rimuove la figura dalla composizione */
  public void remove(Drawing drawing) {
    listDrawing.remove(drawing);
  }
}

Di seguito è presente il codice del programma che andrà a creare i diversi grafici:

public class Program {
    public static void main(String[] args) {
        // inizializziamo tre ellissi
        Ellipse ellipse1 = new Ellipse();
        Ellipse ellipse2 = new Ellipse();
        Ellipse ellipse3 = new Ellipse();
        Ellipse ellipse4 = new Ellipse();

        // inizializziamo tre grafici composti
        CompositeDrawing drawing1 = new CompositeDrawing();
        CompositeDrawing drawing2 = new CompositeDrawing();
        CompositeDrawing drawing3 = new CompositeDrawing();

        // componiamo i diversi grafici
        drawing1.add(ellipse1);
        drawing1.add(ellipse2);
        drawing1.add(ellipse3);

        drawing2.add(ellipse4);

        drawing3.add(drawing1);
        drawing3.add(drawing2);

        // stampiamo il risultato finale
        drawing3.print();
    }
}