Padrão - Factory Method
Published: 2023-01-13 19:54:00

![Pattern Factory](https://miro.medium.com/max/640/0*sTPG2NTEm5ZuvkAr.webp)

O padrão de projeto de fábrica (_Factory Method_) é um padrão de projeto de software que define uma interface para criar um objeto em uma superclasse, mas permite que as subclasses decidam qual classe de objeto instanciar. 

O padrão Método de Fábrica foi criado por Gamma et al. em seu livro "Design Patterns: Elements of Reusable Object-Oriented Software", publicado em 1995. O padrão Método de Fábrica é um dos padrões de criação, que são usados para abstrair a lógica de criação de objetos.

Esse padrão é útil quando você quer que a sua aplicação crie objetos de uma determinada família, mas não se importa com a classe concreta que é instanciada. 

Por exemplo, se você estiver criando uma aplicação de gráficos, poderá ter uma superclasse "Gráfico" com uma interface para desenhar o gráfico, e subclasses concretas para gráficos de barras, gráficos de linhas, gráficos de pizza, etc. Você pode usar o padrão de fábrica para criar um gráfico sem se preocupar com a classe concreta que será instanciada.

Neste padrão temos algumas vatangens, que são:

- Permite a criação de objetos sem conhecer a sua classe concreta. Isso significa que o código cliente não precisa saber como criar um objeto específico, basta solicitar ao Factory Method que crie o objeto para ele. Isso torna o código mais flexível e fácil de manter, pois permite adicionar novas classes sem precisar alterar o código cliente

- Ajuda a separar o código de criação de objetos do código que os utiliza. Isso facilita o gerenciamento do código, pois o Factory Method é responsável por criar os objetos, enquanto o código cliente só precisa saber como usá-los.

- Facilita a modificação do sistema, pois permite adicionar novas classes sem precisar alterar o código cliente. Por exemplo, se você precisa adicionar uma nova classe de produto, basta criá-la e adicioná-la ao Factory Method. O código cliente não precisa ser alterado.

- Permite a criação de objetos de forma mais eficiente, pois o Factory Method pode implementar lógicas de criação mais sofisticadas, como pool de objetos ou cache de objetos. Isso pode melhorar a performance do sistema.


Outra vantagem do Método de Fábrica é que ele permite adicionar novos tipos de objetos com facilidade, bastando adicionar um novo caso para o tipo de objeto desejado no método de fábrica. Isso é mais fácil do que adicionar novas subclasses para cada novo tipo de objeto.

Segue abaixo um simples exemplo de código usando o padrão Factory method.


```js

function createObject(type) {
    return function returnObject(name) {
        return { type, name: name}
    }
}

function factoryMethod (type) {
    switch(type){
        case 'car':
            return createObject(type)
        case 'phone':
            return createObject(type)
        default:
            throw new Error('Unknown type')
    }
}

const createCar = factoryMethod("car");
const myCar = createCar("Ford");
console.log(myCar); // { type: "car", name: "Ford" }

const createPhone = factoryMethod("phone");
const myPhone = createPhone("iPhone");
console.log(myPhone); // { type: "phone", name: "iPhone" }

```

O _factoryMethod_ permite criar objetos de diferentes tipos sem especificar explicitamente a função que será invocada para criar esses objetos.

A função _createObject_ é uma função auxiliar que cria e retorna um objeto com o tipo especificado e um nome. Ela é usada pelo _factoryMethod_, que aceita um tipo como parâmetro e retorna uma nova função que, quando chamada, cria e retorna um objeto desse tipo.

O _factoryMethod_ pode criar dois tipos de objetos: "car" e "phone". Se um tipo diferente for passado para o método de fábrica, uma exceção será lançada.

As duas últimas linhas de código criam duas funções: createCar e createPhone. Essas funções são criadas passando os respectivos tipos para o _abstractMethod_. Elas podem ser usadas para criar objetos desse tipo passando um nome para elas. Por exemplo, myCar é um objeto do tipo "car" com o nome "Ford", enquanto myPhone é um objeto do tipo "phone" com o nome "iPhone".


_Simples, né ?_


Imagine outro cenário na qual a sua gestora de equipe informou que necessita consumir API de CEP e outra de CNPJ para validação de um formulário de cadastro de usuário na sua plataforma.

Os parceiros listados foram:

- [ViaCEP](https://viacep.com.br/)
- [Brasilapi](https://brasilapi.com.br)


Segue a solução abaixo:

```js
const API_URL_CEP = 'https://brasilapi.com.br/api/cep/v1'
const API_URL_CNPJ = 'https://www.receitaws.com.br/v1/cnpj'

function createRequest(url) {
    return function(data) {
        return fetch(`${url}/${data}`).then(response => response.json())
    }
}

function factoryMethod (type) {
    switch(type) {
        case 'cep':
            return createRequest(API_URL_CEP)
        case 'cnpj':
            return createRequest(API_URL_CNPJ)
        default:
            throw new Error('Unknown type')
    }
}

const lookupCep = factoryMethod('cep')
lookupCep('01001000')
    .then(address => {
        console.log(address) // { cep: '01001000', state: 'SP', city: 'São Paulo', neighborhood: 'Sé', street: 'Praça da Sé', service: 'correios' }
})

const lookupCnpj = factoryMethod('cnpj')
lookupCnpj('06990590000123')
    .then(cnpj => {
        console.log(cnpj) // { atividade_principal: [ { code: '63.19-4-00', text: 'Portais, provedores de conteúdo e outros serviços de informação na internet' } ], ... }
})

```

A função createRequest é uma função auxiliar que cria e retorna uma função que faz uma solicitação HTTP à URL especificada, usando o método fetch, e retorna os dados da resposta como um objeto JSON. Ela é usada pelo método de fábrica factoryMethod, que aceita um tipo como parâmetro e retorna uma nova função que, quando chamada, faz uma solicitação à API correta para esse tipo.

O _factoryMethod_ pode criar duas funções diferentes: lookupCep e lookupCnpj. lookupCep é criado passando o tipo "cep" para o _factoryMethod_, enquanto lookupCnpj é criado passando o tipo "cnpj". Essas funções podem ser usadas para obter os dados de um CEP ou CNPJ, respectivamente, passando o valor do CEP ou CNPJ para elas. As duas últimas linhas de código fazem isso, fazendo solicitações às APIs de CEP e CNPJ e exibindo os resultados no console.


**Conclusão.**

O padrão Método de Fábrica é um dos padrões de criação, que são usados para abstrair a lógica de criação de objetos. Ele é um dos 23 padrões de projeto conhecidos coletivamente como "Padrões de Projeto GoF" (GoF Patterns). 

Que pode ser útil em várias situações, como:

- Quando você tem várias classes relacionadas e precisa escolher qual classe concreta será usada para criar um objeto.
- Quando você tem muitas possíveis classes concretas e precisa escolher qual delas será usada para criar um objeto.
- Quando você quer tornar o código mais flexível e escalável, permitindo adicionar novos tipos de objetos com facilidade.


Espero ter ajudado, até a próxima.