Factory Method com PHP
Tags: php, programming, webdev, codenewbie
Published: 2022-09-07 00:16:59

No padrão Factory Method, temos uma interface que implementará o 'básico' que seus objetos deverão possuir. 

Este é mais um padrão de projeto do GOF, onde programamos voltados a interface, deixando a responsabilidade de implementação especificos para cada objeto particular.

Um exemplo prático seria definirmos tipos de pagamentos, existem infinitos tipos e formas de realizarmos um pagamento, mas podemos resumi-los a alguns itens em comum: 

Todo pagamento tem um valor, a moeda (dólar, real), juros, parcelamento etc. Poderiamos ter então uma PagamentoProduct com esses métodos, e cada forma de pagamento deverá implementar esses métodos e definir suas regras. 
 
A 'programação voltada a interfaces'é muito utilizado em Golang, onde para podermos testar os objetos, precisamos primeiro de uma interface que modele o comportamento do mesmo. 

CarroProduct.php:
```
<?php

namespace FactoryMethod\Product;

// Todos os subprodutos de um carro, precisam implementar os métodos desta interface
interface CarroProduct
{
    public function acelerar(): void;
    public function frear(): void;
    public function trocarMarcha(): void;
}
```
Dentro deste arquivo, para diminuir o número de arquivos, eu criei 2 classes diferentes que implementam nossa interface: TeslaModel e Fusca. Este dois são nossos objetos 'concretos' que implementam o modelo (interface). 

```
// Concrete product, ou seja, um objeto concreto que implementa a interface
class TeslaModel implements CarroProduct
{
    public function acelerar(): void
    {
        echo "Tesla acelerando\n";
    }

    public function frear(): void
    {
        echo "Tesla freando\n";
    }

    public function trocarMarcha(): void
    {
        echo "Tesla trocando marcha";
    }
}

// Concrete product, ou seja, um objeto concreto que implementa a interface
class Fusca implements CarroProduct
{
    public function acelerar(): void
    {
        echo "Fusca acelerando\n";
    }

    public function frear(): void
    {
        echo "Fusca freando\n";
    }

    public function trocarMarcha(): void
    {
        echo "Fusca trocando marcha";
    }
}

```

Agora, criamos outra interface, desta vez a que será responsável pelo controle de criação dos nossos objetos, ou seja, a interface responsável por definir nossa fábrica. 

```
CarroFactory.php:

<?php

use FactoryMethod\Product\CarroProduct;

// A carro factory, permite que a gente crie qualquer objeto concreto que implemente a interface CarroProduct
interface CarroFactory 
{
    public function criarCarro(string $modeloDoCarro) : CarroProduct;
}
```
Faremos uso da classe CarroProduct acima, já que nossa Factory (fábrica) será responsável por criar objetos do tipo CarroProduct, ou seja, qualquer classe que implementar nossa interface. 
 
Agora, criaremos 2 classes FuscaFactory e TeslaFactory, que serão as classes responsáveis por criar nosso Fusca e nosso Tesla. 

```
<?php

use FactoryMethod\Product\CarroProduct;
use FactoryMethod\Product\Fusca;

class FuscaFactory implements CarroFactory 
{
    public function criarCarro(string $modeloDoCarro): CarroProduct
    {
        if ($modeloDoCarro == "fusca")
        {
            return new Fusca();
        } else {
            throw new Exception("Modelo de carro invalido!");
        }
    }
}
```
Finalmente, nosso index: 

```

<?php

/**
 * 
 * No padrão Factory Method, temos uma interface que define
 *um contrato para os objetos a serem criados pelas fábricas, que
 *seriam nossos produtos finais. Também temos uma interface que
 *define como nossas classes-fábrica deverão ser construídas.
 * 
 * 
 */

 $teslaFactory = new TeslaFactory();
 $fuscaFactory = new FuscaFactory();

 try 
 {
    $teslas = $teslaFactory->criarCarro('modeloX');
 } 
 catch(Exception $e)
 { 
    echo $e->getMessage();
 }
 
 $teslas->acelerar();
 $teslas->trocarMarcha();
 $teslas->frear();

```

Resumidamente, o método fábrica é muito util quando precisamos criar vários objetos que terão comportamentos similares. Claro que aqui foi um exemplo não tão prático, mas por exemplo, se fosse uma montadora de automóveis real, imagine quantos modelos de carro existem.