Prototype Pattern em PHP
Tags: php, webdev, tutorial, programming
Published: 2022-09-07 23:05:18

Neste padrão os objetos criados servem como uma espécie de protótipo, que serão clonados para a criação de novos objetos. Diferente dos demais padrões de criação, o Prototype utiliza o **próprio** objeto para criar as novas instâncias em vez de usar classes auxiliares para fazer isso.

Este padrão é indicado principalmente quando se quer criar
cópias exatas de um objeto, incluindo seus atributos. Assim, temos um custo muito menor de memória do que instanciar o mesmo objeto muitas vezes.

Imagine que uma livraria precisa 'assinar' o nome do comprador em cada capa de livro. Se fossemos por uma abordagem sem padrões, teriamos que instanciar um novo objeto a cada livro comprado, certo? 

Todo esse 'esforço'computacional somente parar alterar uma propriedade do objeto.

Para isso, vamos utilizar o padrão Prototype que nos da uma solução muito mais leve para esse problema.



- **Prototype**: classe abstrata que define o contrato a ser 'clonado'
- **Concrete Type**: classe concreta que implementa a Prototype.
- **Client**: classes que fazem uso dos objetos. 
_
```
LivroPrototype: 

/**
 * Livro Design Patterns PHP 7
 *  Pagina 73 
 * O objetivo desse padrão é definir alguns objetos que servem
 *como uma instância de protótipo, clonada para a criação de novos
 *objetos. Diferente dos demais padrões de criação, o Prototype
 *utiliza o próprio objeto para criar as novas instâncias em vez de
 *usar classes auxiliares para fazer isso.
 *Este padrão é indicado principalmente quando se quer criar
 *cópias exatas de um objeto, incluindo seus atributos. Assim, temos
 *um custo muito menor de memória do que instanciar o mesmo
 *objeto muitas vezes e, em cada uma dessas vezes, setar exatamente
 *os mesmos valores em suas propriedades. 
 */

namespace Prototype;

abstract class LivroPrototype
{
    protected string $titulo;
    // método mágico __clone() é chamaod quando clonamos uma classe com a palavra clone - de forma abstrata, a implementação deve ser feita nas subclasses
    abstract public function __clone();

    public function  getTitulo(): string
    {
        return $this->titulo;
    }

    public function setTitulo(string $titulo) : LivroPrototype 
    {
        $this->titulo = $titulo;
        return $this;
    }
}

```
A classe LivroPrototype representa o nosso protótipo. Ela
estende da classe abstrata LivroPrototype , herdando assim suas propriedades e métodos.

```
class LivroPhpPrototype extends LivroPrototype
{
    public function __construct()
    {
        $this->setTitulo("Livro PHP");
    }

    public function __clone()
    {
        echo "Livro PHP Clonado\n";
    }
}

```
Abaixo, o código dos clientes: 


```
// CLIENTES 

$compradores = ['Gabriel', 'Anderson', 'Bruno'];

$livroPhp = new LivroPhpPrototype();
$livroPhp->setTitulo("Padroes de projeto em PHP");
print_r($livroPhp);

// criando vários clones 

$livros = [];
foreach($compradores as $nomeComprador)
{
    $livroComprador = clone $livroPhp;
    $livroComprador->setNome($nomeComprador);
    $livros[] = $livroComprador; 
}
print_r($livros);

```
Com isso, a nossa livraria agora pode gerar centenas de livros com assinatura, consumindo muito menos memória que uma solução sem o prototype. 

É importante observar que no ultimo loop, estamos trabalhando sempre com um clone do objeto já instanciado, motificando apenas o nome que seria 'assinado' no livro.


Repositório com código: https://github.com/bbwithpointers/design-patterns-php