Padrão de Projetos – Decorator


Alguns amigos meus me disseram que nos artigos relacionados aos Design Patterns venho me estendendo em explicações e modelos. Para não tornar os artigos longos e sonolentos pretendo ser mais breve e pontual.

Nome: Decorator

O Padrão de Projeto Decorador é o mais adequado para aplicar pequenas alterações ou modicar partde de um conteúdo de um objeto ou funcionalidade sem modificar a estrutura original do objeto.

UML

Design Pattern Decorator (Cd)
Code Example

Neste exemplo, a aplicação é para processar compact discs (CDs). Isto deve ter um método para adicionar as faixas de CD e uma maneira mostrar todas as músicas de um CD. O cliente especificou que o a lista de música do CD deve ser mostrada em uma única linha prefixada pelo número da música.

class CD {

public $trackList;

public function __construct() {

$this->trackList = array();

}

public function addTrack ($track) {

$this->trackList[] = $track;

}

public function getTrackList() {

$output = ”;

foreach ($this->trackList as $num=>$track) {

$output .= ($num + 1)  . ” – {$track}.  “;

}

return $output;

}

}

A class CD contém uma variável pública chamada $trackList, que guarda um array das faixas adicionadas no objeto CD. O construtor inicializa esta variável. O método addTrack() simplismente adiciona uma faixa ao array trackList do objeto CD. Finalmente, o método getTrackList() executa um loop em cada faixa do CD e gera a simples “string” contendo as faixas e seus respectivos números conforme a solicitação do cliente.

Para usar este objeto CD, basta executar o código abaixo:

$tracksDeUmaFonteExterna = array (‘What It Means’, ‘Brr’, ‘Goodbye’);

$myCD = new CD();

foreach ($tracksDeUmaFonteExterna as $track) {

$myCD->addTrack ($track);

}

echo $myCD->getTrackList();

Isto funciona perfeitamente para este exemplo. No entando, os requisitos tiveram uma pequena modificação. Agora, as faixas que são retornadas do objeto precisam estar em caixa alta só no retorno de algumas instancias. Modificar o objeto original não é a melhor prática nem criar um nova classe com relacionamento de herança para cada pequena alteração do objeto original CD. Para isso o Design Pattern Decorator será criado.

class CDTrackListDecoratorCaps {

private $__cd;

public function __construct (CD $cd) {

$this->__cd = $cd;

}

public function makeCaps () {

foreach ($this->__cd->trackList as &$track) {

$track = strtoupper($track);

}

}

}

A classe CDTrackListDecoratorCaps é muito simples. O método __construct() simplismente adiciona a instancia da class CD em um atributo interno private chamado $__cd. Em primeiro momento você pode achar que não é possível modificar o conteúdo do objeto CD por um verdadeiro objeto Decorator, mas o PHP manipula objetos por referencia o que torna isso possível. Embora a instância seja guardada em um atributo interno e privado, qualquer alteração dele imediatamente está disponível no código.

Veja o exemplo da utilização do Decorator na classe CD.

$myCD = new CD();

foreach ($tracksDeUmaFonteExterna as $track) {

$myCD->addTrack($track);

}

$myCDCaps = new CDTrackListDecoratorCaps($myCD);

$myCDCaps->makeCaps();

echo $myCD->getTrackList();

Somente duas linhas no código principal foram necessárias para aplicar a alteração solicitada. A primeira linha é a criação do objeto passando o Objeto CD como parametro, e a segunda linha a execução do makeCaps() o qual efetua a alteração do objeto CD.

Para fazer pequenas modificações no conteúdo ou em alguma funcionalidade existente sem alterar a estrutura dos objetos originais o Design Pattern Decorator deve sempre ser utilizado.

Você pode seguir este artigo através do RSS 2.0 feed. Você pode deixar uma resposta, ou trackback do seu próprio site.

2 Comments »

 
  • Eduardo disse:

    Esse padrão é ótimo para praticar o reaproveitamento de código.

  • Ricardo disse:

    Eu gosto do uso para construção de métodos de trace/debug, como validação de argumentos e tipo. Também é interessante a construção de decorator para microbenchmark fornecendo o delta entre a entrada e a saída de uma determinada classe.

 

Deixe um Comentário

Time limit is exhausted. Please reload CAPTCHA.

*