Design Patterns – Builder em PHP
Olá, mundo!
Como estão?!
Para se ter um código agradável, de fácil documentação, manutenção, dentre outros benefícios. Se faz necessário a adoção de metodologias que enfoquem neste quesito.
Hoje trago uma série de postagens que farei acerca dos Padrões de Projetos, catalogados na consagrada Obra “Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos” , falaremos sobre o Padrão Builder.
Separar a construção de um objeto complexo da sua representação de modo que o
mesmo processo de construção possa criar diferentes representações. – Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos, pág. 114, Editora Bookman 2008
Ao trabalho\\
Bom, iniciaremos nosso Padrão Builder que faz parte do grupo de padrões Criacionais, em que ele se difere dos Padrões Factory e Singleton, pois cria um objeto totalmente preparado e pronto para uma tarefa específica.
Imagine uma fábrica de veículos, em que existem um ou mais modelos distintos, dependendo da categoria do veículo se é um (SUV, Hatch, Wagon ou Utilitário), existem estágios de montagem/fabricação semelhantes, como uma base que os define. No entanto, quando os produtos são distintos, necessitam de procedimentos peculiares, ficou claro a proposta?
Basicamente teremos em nosso padrão as seguintes classes:
- Duas Classes Abstratas que darão a base para o método construtor
- Classe Concreta do Veículo
- E Classe Diretor que visa a organização e disposição dos atributos do veículo, e por fim sua implementação.
No exemplo iremos criar uma fábrica de automóveis, com suas características, modelo, classe, marca, etc.
Para esta motivação citada acima fique bem claro, vamos ao código?
Buider.php
<?php /** * Builder Pattern - Adaptado da Obra "Dive into Design Patterns" * Disponível em: https://sourcemaking.com/design_patterns/builder/php/1 * @version 1.0 * @package Builder * @author Thiago Cantero Mari Monteiro * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro * @license http://www.thiagocantero.com.br/sobre */ abstract class AbstrataVeiculoBuilder { abstract function getVeiculo(); } abstract class AbstrataVeiculoDiretor { abstract function __construct(AbstrataVeiculoBuilder $builder_in); abstract function buildVeiculo(); abstract function getVeiculo(); } class Veiculo { private $veiculo = NULL; private $marca = NULL; private $modelo = NULL; private $motor = NULL; private $ano = NULL; function __construct() { } function showVeiculo() { return $this->veiculo; } function setMarca($marca_in) { $this->marca = $marca_in; } function setModelo($modelo_in){ $this->modelo = $modelo_in; } function setMotor($motor_in) { $this->motor = $motor_in; } function setAno($ano_in) { $this->ano .= $ano_in; } function formaVeiculo() { $this->veiculo = '<html>'; $this->veiculo .= '<head><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"><title>Desgin Pattern Builder PHP</title></head>'; $this->veiculo .= '<body>'; $this->veiculo .= '<table class ="table">'; $this->veiculo .= '<thead>'; $this->veiculo .= '<tr>'; $this->veiculo .= '<th scope="col">Marca</th>'; $this->veiculo .= '<th scope="col">Modelo</th>'; $this->veiculo .= '<th scope="col">Motor</th>'; $this->veiculo .= '<th scope="col">Ano</th>'; $this->veiculo .= '</tr>'; $this->veiculo .= '</thead>'; $this->veiculo .= '<tbody>'; $this->veiculo .= '<tr>'; $this->veiculo .= '<td>'.$this->marca.'</td>'; $this->veiculo .= '<td>'.$this->modelo.'</td>'; $this->veiculo .= '<td>'.$this->motor.'</td>'; $this->veiculo .= '<td>'.$this->ano.'</td>'; $this->veiculo .= '</tr>'; $this->veiculo .= '</tbody>'; $this->veiculo .= '</table>'; $this->veiculo .= '</body>'; $this->veiculo .= '</html>'; } } class VeiculoBuilder extends AbstrataVeiculoBuilder { private $veiculo = NULL; function __construct() { $this->veiculo = new Veiculo(); } function setMarca($marca_in) { $this->veiculo->setMarca($marca_in); } function setModelo($modelo_in) { $this->veiculo->setModelo($modelo_in); } function setMotor($motor_in) { $this->veiculo->setMotor($motor_in); } function setAno($ano_in){ $this->veiculo->setAno($ano_in); } function formaVeiculo() { $this->veiculo->formaVeiculo(); } function getVeiculo() { return $this->veiculo; } } class VeiculoDiretorBuilder extends AbstrataVeiculoDiretor { private $builder = NULL; public function __construct(AbstrataVeiculoBuilder $builder_in) { $this->builder = $builder_in; } public function buildVeiculo() { $this->builder->setMarca('Hyundai'); $this->builder->setModelo('HB20'); $this->builder->setMotor('1.0'); $this->builder->setAno('2018'); $this->builder->formaVeiculo(); } public function getVeiculo() { return $this->builder->getVeiculo(); } } $veiculoBuilder = new VeiculoBuilder(); $veiculoDiretor = new VeiculoDiretorBuilder($veiculoBuilder); $veiculoDiretor->buildVeiculo(); $veiculo = $veiculoDiretor->getVeiculo(); writeln($veiculo->showVeiculo()); writeln(''); function writeln($line_in) { echo $line_in."<br/>"; }
Ao executar o código, devemos ter a seguinte proposta:
Fabricamos nosso Hyundai HB20 1.0, ano 2018! ; )
Mas para que se aplica este padrão de projeto?
Muito simples, quando utilizamos um framework (seja qual for a linguagem), usamos classes que nos provê ferramentas praticamente todas automatizadas, como por exemplo: uma classe de conexão com banco de dados/manipulação de banco de dados, manipulação de templates, e etc. É este o padrão adotado. Por consequência disto, o código tende a ser mais enxuto, fácil de manipular, realizar manutenção e, até mesmo, extensões.
Para melhor entendimento recomendo a leitura da Obra “Dive into Desing Patterns“, obra excelente e bem pragmática, vai direto ao ponto.
Código Fonte no github.