Este artigo carece de reciclagem de acordo com o livro de estilo. Sinta-se livre para editá-lo(a) para que este(a) possa atingir um nível de qualidade superior. (Novembro de 2011)
Esta página cita fontes, mas que não cobrem todo o conteúdo. Ajude a inserir referências (Encontre fontes: ABW  • CAPES  • Google (N • L • A)). (Novembro de 2011)
(Figura 1) Um exemplo genérico da aplicação do padrão Decorator

Decorator, wrapper (ou em português Decorador), é um padrão de projeto de software que permite adicionar um comportamento a um objeto já existente em tempo de execução, ou seja, agrega dinamicamente responsabilidades adicionais a um objeto.[1] Decorators oferecem uma alternativa flexível ao uso de herança para estender uma funcionalidade, com isso adiciona-se uma responsabilidade ao objeto e não à classe.

Motivação

[editar | editar código-fonte]

O Decorator surgiu da necessidade de adicionar um comportamento, funcionalidade ou estado extra a um objeto em tempo de execução, por exemplo quando Herança não é concebível por ser um caso que geraria um número muito alto de sub-classes.

Suponha que existe um objeto Arma, ela pode ter comportamentos diferentes dependendo da munição, dependendo do tipo de mira que tiver, se tiver algum tipo de silenciador ou outro acessório. Imagine criar agora uma sub classe para cada combinação possível de armas, o número de classes aumenta exponencialmente para cada opção a mais que você tiver. É ai que entra o Decorator.

Outro exemplo de utilização desse padrão seria, por exemplo, um sistema de reserva de passagens no qual o passageiro possa adicionar itens e serviços à sua passagem área ou viária. Como bagagens extras, cabine com espaço maior e opções de refeição. Uma árvore de natal que recebe a adição de objetos e luzes que a decoram também é um outro exemplo do mundo real no qual aplicar-se-ia o padrão Decorator.

São diversos os exemplos nos sistemas que usamos no dia-a-dia, cuja função é adicionar responsabilidades e comportamentos à um objeto dinamicamente e que sem esse padrão, a capacidade de personalizar e editar classes tornaria-se inviável.

Consequências

[editar | editar código-fonte]

Aplicabilidade

[editar | editar código-fonte]

Exemplo de uso

[editar | editar código-fonte]
(Figura 2) Um exemplo do que poderia ser feito, caso não usado o padrão Decorator
(Figura 3) Como seria aplicado o padrão decorator no exemplo.

Um exemplo simples e prático da aplicação do Decorator seria colocar acessórios em uma arma, como miras e silenciadores. Um modo de se contornar esse problema seria criar uma interface e criar armas que implementam essa interface (Figura 2), porém isso faria com que tivéssemos muitas classes que implementam essa interface, para apenas dois acessórios teríamos que criar 4 classes (Arma sem acessórios, arma com silenciador, arma com mira, arma com mira e silenciador) tornando essa uma alternativa ruim. Além disso, essa alternativa viola os princípios de baixa acoplação e alta coesão.

Outra solução seria utilizar o Design Pattern Decorator, com esse Design Pattern será possível contornar esse problema de uma forma simples e que não viole nenhum princípio de design. Além disso, ele possibilita que sejam adicionados acessórios durante o tempo de execução. A aplicação do padrão Decorator seria a seguinte (Figura 3).

Abaixo esse exemplo pode ser visto implementado em Java e PHP.

Implementação de Decorator em Java

[editar | editar código-fonte]

Implementação da interface Arma:

public interface Arma{

  public void montar();

}

Implementação da classe ArmaBase:

public class ArmaBase implements Arma{

  @Override
  public void montar(){
    System.out.println("Essa é uma arma base");
  }

}

Implementação da classe ArmaDecorator:

public class ArmaDecorator implements Arma{

  public Arma arma;

  public ArmaDecorator(Arma arma){
    this.arma = arma;
  }

  @Override
  public void montar(){
    this.arma.montar();
  }

}

Implementação da classe Mira:

public class Mira extends ArmaDecorator{

  public Mira(Arma arma){
    super(arma);
  }

  @Override
  public void montar(){
    super.montar();
    System.out.println("Adicionando mira a arma");
  }

}

Implementação da classe Silenciador:

public class Silenciador extends ArmaDecorator{

  public Silenciador(Arma arma){
    super(arma);
  }

  @Override
  public void montar(){
    super.montar();
    System.out.println("Adicionando silenciador a arma");
  }

}

Objetos poderiam ser instanciados da seguinte forma:

/* Monta uma arma com mira e silenciador */
Arma armaCompleta = new Silenciador( new Mira( new ArmaBase() ) );
armaCompleta.montar();

/* Monta uma arma sem acessórios */
Arma armaB = new ArmaBase();
armaB.montar();

/* Monta uma arma com silenciador */
Arma armaComSilenciador = new Silenciador( armaB );
armaComSilenciador.montar();

/* Monta uma arma com mira */
Arma armaComMira = new Mira( armaB );
armaComMira.montar();

Implementação de Decorator em PHP

[editar | editar código-fonte]

Implementação da interface Arma

interface Arma {
    
    public function montar();

}

Implementação da classe ArmaBase:

class ArmaBase implements Arma {
    /** @override */
    public function montar() {
        echo "\nEssa é uma arma base.\n";
    }
}

Implementação da classe ArmaDecorator:

class ArmaDecorator implements Arma {
    protected $arma; 

    public function __construct(Arma $arma) {
        $this->arma = $arma;
    }

    /** @override */
    public function montar() {
        $this->arma->montar();
    }

}

Implementação da classe Mira:

class Mira extends ArmaDecorator {
    public function __construct(Arma $arma) {
        parent::__construct($arma);
    }

    /** @override */
    public function montar() {
        parent::montar();
        echo "Adicionando mira a arma.\n";
    }
}

Implementação da classe Silenciador:

class Silenciador extends ArmaDecorator {
    public function __construct(Arma $arma) {
        parent::__construct($arma);
    }

    /** @override */
    public function montar() {
        parent::montar();
        echo "Adicionando silenciador a arma.\n";
    }
}

Objetos poderiam ser instanciados da seguinte forma:

/* Monta uma arma com mira e com silenciador. */
$armaCompleta = new Silenciador( new Mira( new ArmaBase() ) );
$armaCompleta->montar();

/* Monta uma arma sem acessórios. */
$armaB = new ArmaBase();
$armaB->montar();

/* Monta uma arma com silenciador. */
$armaComSilenciador = new Silenciador( $armaB );
$armaComSilenciador->montar();

/* Monta uma arma com mira. */
$armaComMira = new Mira( $armaB );
$armaComMira->montar();

Referências

  1. SILVA, V. T. Padrões de Design. Acessado em janeiro de 2005.[ligação inativa]
  1. FREEMAN, Eric e Elisabeth. Use a Cabeça! Padrões de projetos. Acessado em outubro de 2016
  2. SourceMaking. Design Patterns - Decorator. Acessado em outubro de 2016
  3. JournalDev. Decorator Design Pattern in Java Example. Acessado em outubro de 2016

Ver também

[editar | editar código-fonte]
Este artigo sobre informática é um esboço. Você pode ajudar a Wikipédia expandindo-o.vde