Rientrante in un nuovo tutorial del mese, questo articolo sarà il primo di tanti in cui saranno descritti i principali Design Patterns nell’ambito dell’Ingegneria del Software. Ma, prima di tutto, cosa sono i Design Patterns?

Secondo Wikipedia il Design Pattern in informatica e specialmente nell'ambito dell'ingegneria del software, è un concetto che può essere definito "una soluzione progettuale generale ad un problema ricorrente". Si tratta di una descrizione o modello logico da applicare per la risoluzione di un problema che può presentarsi in diverse situazioni durante le fasi di progettazione e sviluppo del software, ancor prima della definizione dell'algoritmo risolutivo della parte computazionale. È un approccio spesso efficace nel contenere o ridurre il debito tecnico.

I design pattern orientati agli oggetti tipicamente mostrano relazioni ed interazioni tra classi o oggetti, senza specificare le classi applicative finali coinvolte, risiedendo quindi nel dominio dei moduli e delle interconnessioni. Ad un livello più alto, ci sono invece i pattern architetturali che hanno un ambito ben più ampio, descrivendo un pattern complessivo adottato dall'intero sistema, la cui implementazione logica dà vita a un framework.

Il Design Pattern che andremo ad analizzare in questo articolo è quello chiamato Decorator.

IL DESIGN PATTERN DECORATOR

Il Design Pattern Decorator consente all'utente di aggiungere nuove funzionalità a un oggetto esistente senza alterarne la struttura. Questo tipo di modello di progettazione rientra nel modello strutturale, in quanto funge da wrapper per la classe esistente.

Questo modello crea una classe decoratore che avvolge quella originale e fornisce funzionalità aggiuntive mantenendo intatta la firma dei metodi di classe.

Dimostreremo l'uso del Pattern Decorator tramite il seguente esempio in cui decoreremo una forma con un pò di colore senza alterare la classe della forma stessa.

IMPLEMENTAZIONE

Di seguito creeremo un'interfaccia Shape e classi concrete per la sua implementazione. Svilupperemo quindi una classe decoratore astratta ShapeDecorator che implementa l'interfaccia Shape e ha l'oggetto Shape come variabile di istanza.

RedShapeDecorator è una classe concreta che implementa ShapeDecorator.

DecoratorPatternDemo, la nostra classe demo utilizzerà RedShapeDecorator per decorare gli oggetti Shape.

STEP 1

Creiamo l’interfaccia

Shape.java

public interface Shape {

   void draw();

}

STEP 2

Creiamo la classe concreta che implementa la stessa interfaccia

Rectangle.java

public class Rectangle implements Shape {

 

   @Override

   public void draw() {

      System.out.println("Shape: Rectangle");

   }

}

Circle.java

public class Circle implements Shape {

 

   @Override

   public void draw() {

      System.out.println("Shape: Circle");

   }

}

STEP 3

Creiamo la classe decoratore astratta che implementa l’interfaccia the Shape

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape {

   protected Shape decoratedShape;

 

   public ShapeDecorator(Shape decoratedShape){

      this.decoratedShape = decoratedShape;

   }

 

   public void draw(){

      decoratedShape.draw();

   }   

}

STEP 4

Creiamo la classe decorator concreta che estende la classe ShapeDecorator.

RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator {

 

   public RedShapeDecorator(Shape decoratedShape) {

      super(decoratedShape);         

   }

 

   @Override

   public void draw() {

      decoratedShape.draw();         

      setRedBorder(decoratedShape);

   }

 

   private void setRedBorder(Shape decoratedShape){

      System.out.println("Border Color: Red");

   }

}

STEP 5

Usiamo la classe RedShapeDecorator per decorare gli oggetti di tipo Shape

DecoratorPatternDemo.java

public class DecoratorPatternDemo {

   public static void main(String[] args) {

 

      Shape circle = new Circle();

 

      Shape redCircle = new RedShapeDecorator(new Circle());

 

      Shape redRectangle = new RedShapeDecorator(new Rectangle());

      System.out.println("Circle with normal border");

      circle.draw();

 

      System.out.println("\nCircle of red border");

      redCircle.draw();

 

      System.out.println("\nRectangle of red border");

      redRectangle.draw();

   }

}

STEP 6

Verifichiamo l’output

Circle with normal border

Shape: Circle

 

Circle of red border

Shape: Circle

Border Color: Red

 

Rectangle of red border

Shape: Rectangle

Border Color: Red

Articoli del tutorial