Padrões criacionais Factory
Tags: braziliandevs, beginners, todayilearned
Published: 2022-05-12 01:33:16

### Today I Learned 11/05/2022
[Factory](#factory)
[Propósito](#propósito)
[Problema](#problema)
[Solução](#solução)
[Estrutura](#estrutura)
[Implementação](#implementação)
[Referencias](#referencias)

# Factory

### Propósito
Fornecer uma interface para criar objetos em uma superclasse, mas permitir que as subclasses alterem o tipo de objetos que serão criados

### Problema
Se você tem um código muito acoplado a uma á uma classe em especifico, caso um dia precise adicionar uma outra classe vai ter problemas, por exemplo, uma empresa de logistica que usa somente caminhões, e o sistema está fortemente acoplado a classe de caminhão, caso algum dia queira ser implementada a classe `navio` isso vai gerar uma refatoração gigantesca no código

### Solução
O padrão factory sugere substituir as chamadas diretas de construção de objetos, nesse caso caminhão para um método factory e ai esse factory vai ficar responsavel por criar e retornar os objetos que nesse caso chamamos de produtos

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kcnm0vcpxgqrdavboya.png)

Nesse exemplo do site refactoring guru, podemos ver que temos uma classe `Logistics` que contem um método `createTransport` que é uma factory, as classes `RoadLogistics` e `SeaLogistics` implementam essa classe Logistics e modificam o `createTransport` para retornar um caminhão e um návio respectivamente

Porem existe uma limitação, as subclasses só podem retornar tipos diferentes de produtos caso eles implemente uma mesma interface em comum. Isso ajuda para que quando o cliente faça uma chamada ele apenas precisa saber qual a interface desses produtos e pode tratar todos da mesma forma pois ele sabe que todos vão ter os mesmos métodos

### Estrutura

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s33w2snzlznk8tb5f8m7.png)
 

1. O Produto declara a interface que que os objetos vão implementar

2. O produto concreto A e B são diferentes implementações da interface Produto

3. A classe Creator tem um método factory que cria um produto do tipo Produto
(Apesar do nome a principal responsabilidade da classe creator não é criar produtos)

4. Criadores concretos sobescrevem a classe Creator para retornar diferente produtos no seus metodos factory

### Implementação

```js
abstract class Creator {
    public abstract factoryMethod(): Product;
    public someOperation(): string {
        const product = this.factoryMethod();
        console.log(product.opertation());
    }
}
```

```js
class ConcreteCreator1 extends Creator {
    public factoryMethod(): Product {
        return new ConcreteProduct1();
    }
}

class ConcreteCreator2 extends Creator {
    public factoryMethod(): Product {
        return new ConcreteProduct2();
    }
}
```

os concrete creators vão extender o Creator e mudar apenas o método factory

```js
interface Product {
    operation(): string;
}

class ConcreteProduct1 implements Product {
    public operation(): string {
        return '{Result of the ConcreteProduct1}';
    }
}

class ConcreteProduct2 implements Product {
    public operation(): string {
        return '{Result of the ConcreteProduct2}';
    }
}
```

```js
function clientCode(creator: Creator) {
    console.log(creator.someOperation());
}
```

a partir dai o `clientCode` precisa apenas receber qualquer classe que extende o creator e ele tem certeza que essa classe vai ter o método `someOperation` que pode fazer coisas  diferentes como por exemplo o no exemplo do barco e caminhão ambos podem ter o método delivery que funcionam de formas diferentes mas isso não import para o `clientCode`

## Referencias 

- https://refactoring.guru/pt-br/design-patterns/factory-method