Decorator

Da Wikipedia, l'enciclopedia libera.
Diagramma delle classi del pattern Decorator

Nella programmazione ad oggetti, il decorator è uno dei pattern fondamentali, definiti originariamente dalla gang of four.

Il design pattern decorator consente di aggiungere durante il run-time nuove funzionalità ad oggetti già esistenti. Questo viene realizzato costruendo una nuova classe decoratore che "avvolge" l'oggetto originale. Al costruttore del decoratore si passa come parametro l'oggetto originale. È altresì possibile passarvi un differente decoratore. In questo modo, più decoratori possono essere concatenati l'uno all'altro, aggiungendo così in modo incrementale funzionalità alla classe concreta (che è rappresentata dall'ultimo anello della catena).

La concatenazione dei decoratori può avvenire secondo una composizione arbitraria: il numero di comportamenti possibili dell'oggetto composto varia dunque con legge combinatoriale rispetto al numero dei decoratori disponibili.

Questo pattern si pone come valida alternativa all'uso dell'ereditarietà singola o multipla. Con l'ereditarietà, infatti, l'aggiunta di funzionalità avviene staticamente secondo i legami definiti nella gerarchia di classi e non è possibile ottenere al run-time una combinazione arbitraria delle funzionalità, né la loro aggiunta/rimozione.

Struttura di un decorator[modifica | modifica wikitesto]

  • Component: definisce l'interfaccia dell'oggetto a cui verranno aggiunte nuove funzionalità.
  • ConcreteComponent: definisce l'oggetto concreto al quale aggiungere le funzionalità.
  • Decorator: mantiene un riferimento all'oggetto Component e definisce un'interfaccia conforme all'interfaccia Component.
  • ConcreteDecorator: aggiunge le funzionalità al Component.

Funzionamento[modifica | modifica wikitesto]

Il Decorator manda le richieste al Component che può svolgere le operazioni precedenti e successive alla spedizione della richiesta.

In questo modo si ottiene una maggior flessibilità, tanti piccoli oggetti al posto di uno molto complicato, andando a modificare il contorno e non la sostanza di una classe.

Esempio[modifica | modifica wikitesto]

PHP[modifica | modifica wikitesto]

abstract class Componente
{
    protected $contenitore;
    protected $valore;
    abstract public function ottieniContenitore();
    abstract public function ottieniValore();
}

class ComponenteConcreto extends Componente
{
    public function __construct()
    {
        $this->valore = 1000;
        $this->contenitore = "Componente Concreto:\t{$this->valore}\n";
    }

    public function ottieniContenitore()
    {
        return $this->contenitore;
    }

    public function ottieniValore()
    {
        return $this->valore;
    }
}

abstract class Decoratore extends Componente
{
    
}

class DecoratoreConcreto1 extends Decoratore
{
    public function __construct(Componente $contenitore)
    {
        $this->valore = 1000;
        $this->contenitore = $contenitore;
    }

    public function ottieniContenitore()
    {
        return $this->contenitore->ottieniContenitore() . "Decoratore Concreto 1:\t{$this->valore}\n";
    }

    public function ottieniValore()
    {
        return $this->valore + $this->contenitore->ottieniValore();
    }
}

class DecoratoreConcreto2 extends Decoratore
{
    public function __construct(Componente $contenitore)
    {
        $this->valore = 1000;
        $this->contenitore = $contenitore;
    }

    public function ottieniContenitore()
    {
        return $this->contenitore->ottieniContenitore() . "Decoratore Concreto 2:\t{$this->valore}\n";
    }

    public function ottieniValore()
    {
        return $this->valore + $this->contenitore->ottieniValore();
    }
}

class Cliente
{
    private $componente;

    public function __construct()
    {
        $this->componente = new ComponenteConcreto();
        $this->componente = $this->avvolgiComponente($this->componente);

        echo $this->componente->ottieniContenitore();
        echo "Cliente:\t\t";
        echo $this->componente->ottieniValore();
    }

    private function avvolgiComponente(Componente $componente)
    {
        $componente1 = new DecoratoreConcreto1($componente);
        $componente2 = new DecoratoreConcreto2($componente1);
        return $componente2;
    }
}

echo "\n\n";
$cliente = new Cliente();

// Risultato: #quanton81

//Componente Concreto:      1000
//Decoratore Concreto 1:	1000
//Decoratore Concreto 2:	1000
//Cliente:                  3000

Voci correlate[modifica | modifica wikitesto]

Altri progetti[modifica | modifica wikitesto]