Abstract Factory - Construindo Motos Honda
Tags: designpatterns
Published: 2023-11-17 16:31:12


Quando adquiri maior idade, resolvi comprar minha primeira moto Honda, as opções da época eram Cargo, Start, Fan e Titan, opções que dentre elas, a de maior agrado para mim foi a Titan.

Como todos os modelos possuem características comuns, irei 
utilizar algumas que julgo ser importantes para compor nosso exemplo do Pattern [Abstract Factory](https://refactoring.guru/pt-br/design-patterns/abstract-factory).

Vejamos abaixo as características especiais de cada modelo

|Modelo|CC|Roda|Seta|Freio|
|-|-|-|-|-|
|Cargo|125|Ferro|Laranja|Tambor|
|Start|160|Ferro|Laranja|Tambor|
|Fan|160|Liga Leve|transparente|Disco|
|Titan|160|Liga Leve|transparente|Combi Break|

Agora vamos imaginar que cada modelo é montado em um estado do país

|Modelo|Localidade|
|-|-|
|Cargo|Amazonas|
|Start|Bahia|
|Fan|Minas Gerais|
|Titan|São Paulo|

E que a cada compra, a devida fabrica monta o modelo de sua especialidade e envia para o cliente a que encomendou.

**Bom, o Abstract Factory é isso, ele é um conjunto de uma ou mais fabricas isoladas que na sua produção, cria subtipos de sua especialidade.**

Uma forma de  tentar entender o abstract factory seria assim:

**Vendedor Pedro**: Olá eu sou novo aqui no setor de vendas e acabei de fechar uma venda para o  cliente Reginaldo, durante o processo de venda ele comprou uma Honda Titan Ex, onde posso fazer a solicitação de montagem e entrega da moto?

**Vendedora Ana**: Hmm, você precisa solicitar uma montagem para o João, ele é quem recebe os pedidos e encaminha para as fabricas corretas.

**Vendedor Pedro**: Ah, obrigado.

**Vendedor Pedro**: Olá João, gostaria de solicitar uma montagem de uma Honda Titan, você poderia me ajudar?

**João**: Sim, é pra já! ... Seu pedido foi encaminhado para a fabrica de São Paulo e assim que recebermos o pedido, eu te aviso.

Vendedor Pedro: Show! Muito obrigado João!

**Nessa mini conversa percebemos que as fabricas são quem recebe as solicitações e seu objetivo é devolver os subtipos de sua especialidade**

## Praticando
Após mostrar o objetivo do Abstract Factory, agora é hora de colocar a mão na massa! Espero que até aqui esteja tudo bem!
 
1 - Ao iniciar o Pattern, sugiro que comece definindo os tipos e subtipos de cada objeto parte da moto.

```c#
    public abstract class Cilindrada
    {
        public abstract void Montar();
    }
    public class Cilindrada125 : Cilindrada
    {
        public override void Montar()
        {
            Console.WriteLine("Montando Motor 125CC");
        }
    }
    public class Cilindrada160 : Cilindrada
    {
        public override void Montar()
        {
            Console.WriteLine("Montando Motor 160CC");
        }

    }
```
```C#
    public abstract class Roda
    {
        public abstract void Montar();
    }
    public class RodaFerro : Roda
    {
        public override void Montar()
        {
           Console.WriteLine("Montando Roda de Ferro");
        }
    }
    public class RodaLigaLeve : Roda
    {
        public override void Montar()
        {
           Console.WriteLine("Montando Roda de Liga Leve");
        }
    }
```
```c#
        public abstract class Seta
    {
        public abstract void Montar();
    }
    public class SetaLaranja : Seta
    {
        public override void Montar()
        {
            Console.WriteLine("Montando Seta Laranja");
        }
    }
    public class SetaTransparente : Seta
    {
        public override void Montar()
        {
            Console.WriteLine("Montando Seta Transparente");
        }
    }

```

```c#
    public abstract class Freio
    {
        public abstract void Montar();
        
    }
    public class FreioTambor : Freio
    {
        public override void Montar()
        {
           Console.WriteLine("Montando Freio a Tambor");
        }
    }
    public class FreioDisco : Freio
    {
        public override void Montar()
        {
           Console.WriteLine("Montando Freio a Disco");
        }
    }
    public class FreioCombiBreak : Freio
    {
        public override void Montar()
        {
           Console.WriteLine("Montando Freio Combi Break");
        }
    }
```

2 - Após os tipos criados, você pode criar os Abstract Factories
> Note que há uma interface ou  uma classe abstrata que será herdada pelas respectivas Abstract Factories concretas.

```c#
    public interface AbstractFactoryEstado
    {
        Cilindrada AddMotor();
        Seta AddSeta();
        Roda AddRoda();
        Freio AddFreio();
    }
```
```c# 
    public class AbstractFactoryAmazonas : AbstractFactoryEstado
    {
        public Freio AddFreio()
        {
            return new FreioTambor();
        }

        public Cilindrada AddMotor()
        {
            return new Cilindrada125();
        }

        public Roda AddRoda()
        {
            return new RodaFerro();
        }

        public Seta AddSeta()
        {
            return new SetaLaranja();
        }
    }
```
 
```c#
    public class AbstractFactoryBahia : AbstractFactoryEstado
    {
        public Freio AddFreio()
        {
            return new FreioTambor();
        }

        public Cilindrada AddMotor()
        {
            return new Cilindrada160();
        }

        public Roda AddRoda()
        {
            return new RodaFerro();
        }

        public Seta AddSeta()
        {
            return new SetaLaranja();
        }
    }
```

```c#
    public class AbstractFactoryMinasGerais : AbstractFactoryEstado
    {
        public Freio AddFreio()
        {
            return new FreioDisco();
        }

        public Cilindrada AddMotor()
        {
            return new Cilindrada160();
        }

        public Roda AddRoda()
        {
            return new RodaLigaLeve();
        }

        public Seta AddSeta()
        {
            return new SetaTransparente();
        }
    }
```
 
```c#
    public class AbstractFactoryBahia : AbstractFactoryEstado
    {
        public Freio AddFreio()
        {
            return new FreioCombiBreak();
        }

        public Cilindrada AddMotor()
        {
            return new Cilindrada160();
        }

        public Roda AddRoda()
        {
            return new RodaLigaLeve();
        }

        public Seta AddSeta()
        {
            return new SetaTransparente();
        }
    }
```
3 - Por fim, você só precisa da rotina que faz a construção do objeto.


```c#
    public class AbstractFactoryMotoCreator
    {
        public void Create(AbstractFactoryMoto abstractFactory)
        {
            Cilindrada? Cilindrada = null;
            Seta? Seta  = null;
            Roda? Roda  = null;
            Freio? Freio = null;
            
            Cilindrada = abstractFactory.AddMotor();
            Seta = abstractFactory.AddSeta();
            Roda = abstractFactory.AddRoda();
            Freio = abstractFactory.AddFreio();

            Cilindrada.Montar();
            Seta.Montar();
            Roda.Montar();
            Freio.Montar();
        }
    }
```
> Note que quem define o modelo da moto que será criada é o parametro `abstractFactory`


Agora é só chamar e passar um abstract factory concreto para a rotina de criação.

```c#

AbstractFactoryMotoCreator abstractFactoryMoto = new ();
Console.WriteLine();
abstractFactoryMoto.Create(new AbstractFactoryMotoCargo());
Console.WriteLine();
abstractFactoryMoto.Create(new AbstractFactoryMotoStart());
Console.WriteLine();
abstractFactoryMoto.Create(new AbstractFactoryMotoFan());
Console.WriteLine();
abstractFactoryMoto.Create(new AbstractFactoryMotoTitan());
Console.WriteLine();

```
 
Saída

```console

Montando Motor 125CC
Montando Seta Laranja
Montando Roda de Ferro
Montando Freio a Tambor

Montando Motor 160CC
Montando Seta Laranja
Montando Roda de Ferro
Montando Freio a Tambor

Montando Motor 160CC
Montando Seta Transparente
Montando Roda de Liga Leve
Montando Freio a Disco

Montando Motor 160CC
Montando Seta Transparente
Montando Roda de Liga Leve
Montando Freio Combi Break

```

[Github](http://github.com/reginaldo-marinho)

[Meu Projeto](https://rucula-js.github.io/)

[Contribua, favorite ⭐](https://github.com/rucula-js/rucula-js)