Padrões de Projeto os Design Patterns: Padrão Factory
| janeiro 9th, 2009Dando continuidade aos designer patterns, vou falar um pouco hoje do Designer Factory.
Uma definição para o Factory seria, definir uma interface única para criação de objetos, deixando a cargo da classe Factory decidir qual instância de subclasse deve ser feita.
Trocando em miudos, é como uma central telefonica, você liga para apenas 1 número que você conhece, pergunta para a telefonista o que deseja, e ele te retorna o número correspondido ao seu pedido.
É bastante comum encontrarmos esse padrão em frameworks, ferramentas e bibliotecas.
Bom vamos ao um exemplo prático pois por enquanto está tudo lindo, sabemos que podemos encapsular subclasses em uma classe, fornecendo assim uma instância única, logo se num futuro é necessário fazer alterações, precisamos mudar em apenas um local.
Jõao um famoso empresário da cidade, decide criar uma lancheria, então logo vai para o seu sobrinho dono de uma empresa de programação na cidade e passa os requisitos, nada mais que 1 cardápio com os preços dos lanches tendo 3 tipos de lanches, X-Gordura, X-Maionese, X-Ovo, cada 1 com 1 preço diferente.
José que também é sobrinho do Jõao, diz logo para os programdores tarefa simples, criamos 1 classe que armazena o lanche e receba como parâmetro o preço…
Todos concluem ser uma ótima solução até que depois da entrega, Jõao resolve alterar o preço de 1 dos lanches, para concorrer com outra lancheria que abriu nas proximidades. Pede ao seu sobrinho para alterar o preço do lanche.
E o sobrinho disse que demoraria 6 meses, para fazer isso… José envocado, mas como se para fazer o programa todo demorou 2 meses…
Seu sobrinho responde é que vou ter que alterar os 200 códigos onde está o preço desse lanche!
Conclusão! menos é mais, e é isso que ocorre, vamos fazer essa simples implementação da lancheria com o Padrão Factory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | < ?php abstract class Lanche { abstract public function pegar_preco(); } class XgorduraLanche extends Lanche { public function pegar_preco() { return 2.90; } } class XmaioneseLanche extends Lanche { public function pegar_preco() { return 3.90; } } class XovoLanche extends Lanche { public function pegar_preco() { return 6.90; } } class LancheFactory { public static function lanche($type) { switch ($type) { case 'Xgordura': return new XgorduraLanche(); case 'Xmaionese': return new XmaioneseLanche(); default: return new XovoLanche(); } } } $lanche = LancheFactory::lanche( 'Xgordura' ); echo $lanche->pegar_preco() . '<br />'; $lanche = LancheFactory::lanche( 'Xmaionese' ); echo $lanche->pegar_preco() . '<br />'; $lanche = LancheFactory::lanche( 'Xovo' ) ; echo $lanche->pegar_preco() . '<br />'; ?> |
Como podemos ver foi muito simples a implementação, criamos uma classe abstrata onde dizemos quais são os métodos que temos que implementar nos tipos de lanches, criamos os diversos tipos de lanches extendendo ele da classe abstrata, logo após fizemos a classe factory, com 1 método statico que passamos como parâmetro o tipo do lanche que queremos, dentro do método temos 1 controle com um block swich, e por fim retorna o preço de cada tipo de lanche.
O que pode ser feito é não usar o controle com switch e chamar dinâmicamente a classe, além de adicionar um tratamento de erro para evitar quando informado o tipo errado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | < ?php abstract class Lanche { abstract public function pegar_preco(); } class XgorduraLanche extends Lanche { public function pegar_preco() { return 2.90; } } class XmaioneseLanche extends Lanche { public function pegar_preco() { return 3.90; } } class XovoLanche extends Lanche { public function pegar_preco() { return 6.90; } } class LancheFactory { public static function lanche($type) { $type .= 'Lanche'; if (class_exists($type)) { return new $type(); } else { throw new Exception('Nao tem essa classe!!'); } } } try { $lanche = LancheFactory::lanche( 'Xpicanha' ); echo $lanche->pegar_preco() . '<br />'; } catch (Exception $e) { echo 'Informamos que não temos esse pedido no nosso cardápio! <br />'; } try { $lanche = LancheFactory::lanche( 'Xgordura' ); echo $lanche->pegar_preco() . '<br />'; } catch (Exception $e) { echo 'Informamos que não temos esse pedido no nosso cardápio! <br />'; } try { $lanche = LancheFactory::lanche( 'Xovo' ); echo $lanche->pegar_preco() . '<br />'; } catch (Exception $e) { echo 'Informamos que não temos esse pedido no nosso cardápio! <br />'; } try { $lanche = LancheFactory::lanche( 'Xmaionese' ); echo $lanche->pegar_preco() . '<br />'; } catch (Exception $e) { echo 'Informamos que não temos esse pedido no nosso cardápio! <br />'; } ?> |
Esse foi um exemplo simples, mas em prática podemos se deparar em boa hora de usar o Factory, como tratamento de diversos tipos, como por exemplo imagens, arquivos de música, até mesmo banco de dados entre outros.
Qualquer dúvida comentem!