Aplicando o Decorator em PHP (design pattern)


O que é Decorator?

O padrão Decorator é um padrão de projeto estrutural, que nos permite adicionar um novo comportamento ou adicionais a um objeto durante a execução, dependendo da situação.

Objetivo do Decorator

Tem como objetivo tornar flexivel aplicações mais complexas onde é necessario acrescentar comportamentos e funcionalidades nos objetos e entre outras.

A ideia é substituir herença por composição.

Exemplo:

Imagina que você foi a uma lanchonete, comprou um x-burger e adiciou mostarda, ja seu amigo pediu um x-burger com catchup extra.

O objeto é o x-burger e recebeu adicionais,  então:

Usando Herança teriamos “xBurger” (classe pai), “xBurgerMostarda” (classe filha) e “xBurgerCatchup” (classe filha).  // Desculpa os exemplos, mas são apenas para compreensão

Agora imagina se necessitassemos de criar outros adicionais (cebola, alface e etc)…vamos piorar a situação, imagina que podemos adicionar 2, 3, 4 complementos ao mesmo tempo.

Como fariamos com a herança?
Criariamos a horrivel sub-classe “xBurgerMostardaCatchupCebola” ?

Seu sistema ficaria enorme, com varias classes, duplicação de códigos, acoplado e assim vai…

Por isso o Decorator propoem usar, para casos mais complexos, composição ao invés de herança.
Exemplo:

<?php
abstract class behavior {
	abstract function preparo();
}

class hanburger extends behavior
{
	private $burger ='carne';
	private $pao = 'frances';
	public function preparo() {
		return "Pão {$this->pao} com {$this->burger}";
	}

}

abstract class decorator extends behavior {
	protected $add;
	public function __construct(behavior $add){
		$this->add = $add;
	}
}

class mostarda extends decorator {
	public function preparo(){
		$add = $this->add->preparo();
		return "{$add} mais mostarda";
	}
}

class catchup extends decorator {
	public function preparo(){
		$add = $this->add->preparo();
		return "{$add} mais catchup";
	}
}

Vou criar um Pão com carne mais catchup:

<?php
$hanburger = new catchup(new hanburger());
echo $hanburger->preparo();

Imprimirá:
Pão frances com carne mais catchup

Vou criar um Pão com carne mais mostarda mais catchup:

<?php
$hanburger = new catchup(new mostarda(new hanburger()));
echo $hanburger->preparo();

Imprimirá:
Pão frances com carne mais mostarda mais catchup.

Outro exemplo é o editor de texto html (WYSIWYG), através dele podemos ‘decorar’ um texto, adicionar cor, tamanho e borda ao texto e entre outras.

Seguindo essa ideia, criei um simples Decorator apenas para compreensão, porem deixo claro que é apenas um exemplo simples e, neste caso, o uso do Decorator é desnecessário em produção.

<?php
abstract class Node
{
abstract function tag();
}

class Paragrafo extends Node {
private $txt;
public function __construct($txt){
$this->txt = $txt;
}
public function tag(){
return "<p>". $this->txt ."</p>";
}

}

abstract class UnionNode extends Node {
protected $node;
public function __construct(Node $node){
$this->node = $node;
}
}

class Header extends UnionNode {

public function tag(){
echo "<h1>". $this->node->tag() ."</h1>";
}

}

$html = new Header(new Paragrafo(abc));
print_r($html->tag());

Pros:

  • Promove flexibilidade
  • Evita a duplicação de código
  • facilita a manutenção (eliminação, adição e alteração de funcionalidade)

Contras:

  • Conforme a complexibilidade pode se tornar confuso
  • Código extenso

OBS:
Os exemplos mostrados, são apenas para compreensão do conceito Decorator, assim como, os códigos criados servem apenas para entender como funciona na prática. Aconselho o uso do Decorator quando sua aplicação necessitar de combinação, adição de coisas ou funcionabilidades em tempo de execução e o nivel de complexibilidade e flexibilidade exigidos sejam tão altos que torna-se penoso fazer através da herança.

,

  1. #1 by Respiratory Therapist on 25 de janeiro de 2011 - 22:36

    My cousin recommended this blog and she was totally right keep up the fantastic work!

(não será publicado)