---
title: "Comparação de Factories"
type: "design-pattern"
slug: "factory-comparison"
url: "http://localhost:3000/pt-br/design-patterns/factory-comparison.md"
---
# Comparação de Factories

Este artigo mostrará a diferença entre:

1. Factory
2. Método de criação
3. Método de criação estático (ou de fábrica)
4. Simple factory
5. padrão [Factory Method](/pt-br/design-patterns/factory-method)
6. padrão [Abstract Factory](/pt-br/design-patterns/abstract-factory)

Você encontra referências a esses termos por toda a web. Embora possam parecer semelhantes, todos têm significados diferentes. Muita gente não percebe isso, o que leva à confusão e a mal-entendidos.

Então vamos tentar descobrir a diferença e resolver esse problema de uma vez por todas.

## 1\. Factory

**Factory** é um termo ambíguo que designa uma função, método ou classe que deveria produzir alguma coisa. Na maioria das vezes, factories produzem objetos. Mas também podem produzir arquivos, registros em bancos de dados, etc.

Por exemplo, qualquer uma destas coisas pode ser informalmente chamada de “factory”:

* uma função ou método que cria a GUI de um programa;
* uma classe que cria usuários;
* um método estático que chama o construtor de uma classe de uma forma específica;
* um dos padrões de projeto de criação.

Normalmente, quando alguém diz a palavra “factory”, o significado exato deveria ficar claro pelo contexto. Mas, se você estiver em dúvida, simplesmente pergunte. Há uma chance de que o próprio autor não saiba.

## 2\. Método de criação

**Método de criação** é definido no livro [Refactoring To Patterns](https://refactoring.guru/ref-to-patterns-book) como “um método que cria objetos”. Isso significa que todo resultado do padrão factory method é um “método de criação”, mas não necessariamente o contrário. Também significa que você pode substituir o termo “método de criação” em todos os lugares onde Martin Fowler usa o termo “factory method” em [Refactoring](https://refactoring.guru/ref-book) e onde Joshua Bloch usa o termo “static factory method” em [Effective Java](https://refactoring.guru/effective-java-book).

Na realidade, o método de criação é apenas um invólucro em torno de uma chamada ao construtor. Ele pode simplesmente ter um nome que expressa melhor suas intenções. Por outro lado, pode ajudar a isolar seu código de mudanças no construtor. Ele poderia até conter alguma lógica específica que retornaria objetos existentes em vez de criar novos.

Muita gente chamaria esses métodos de “factory method” só porque eles produzem novos objetos. A lógica é simples: o método cria objetos e, como todas as _factories_ criam objetos, esse método claramente deveria ser um _factory method_. Naturalmente, há muita confusão quando se trata do verdadeiro padrão [Factory Method](/pt-br/design-patterns/factory-method).

No exemplo a seguir, `next` é um método de criação:

class Number {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function next() {
        return new Number ($this->value + 1);
    }
}

## 3\. Método de criação estático

**Método de criação estático** é um método de criação declarado como `static`. Em outras palavras, ele pode ser chamado a partir de uma classe e não exige que um objeto seja criado.

Não se confunda quando alguém chamar métodos como esse de “static factory method”. Isso é só um mau hábito. O [Factory Method](/pt-br/design-patterns/factory-method) é um padrão de projeto que depende de herança. Se você o tornar `static`, não poderá mais sobrescrevê-lo em subclasses, o que anula o propósito do padrão.

Quando um método de criação estático retorna novos objetos, ele se torna um construtor alternativo.

Ele pode ser útil quando:

* Você precisa ter vários construtores diferentes com propósitos distintos, mas cujas assinaturas coincidem. Por exemplo, ter ao mesmo tempo `Random(int max)` e `Random(int min)` é impossível em Java, C++, C# e muitas outras linguagens. E a solução alternativa mais popular é criar vários métodos estáticos que chamam o construtor padrão e definem os valores apropriados em seguida.
* Você quer reutilizar objetos existentes em vez de instanciar novos (veja o padrão [Singleton](/pt-br/design-patterns/singleton)). Os construtores, na maioria das linguagens de programação, têm que retornar novas instâncias da classe. O método de criação estático é uma solução alternativa para essa limitação. Dentro de um método estático, seu código pode decidir se cria uma nova instância chamando o construtor ou se retorna um objeto existente a partir de algum cache.

No exemplo a seguir, o método `load` é um método de criação estático. Ele oferece uma forma conveniente de recuperar usuários de um banco de dados.

class User {
    private $id, $name, $email, $phone;

    public function __construct($id, $name, $email, $phone) {
        $this->id = $id;
        $this->name = $name;
        $this->email = $email;
        $this->phone = $phone;
    }

    public static function load($id) {
        list($id, $name, $email, $phone) = DB::load_data('users', 'id', 'name', 'email', 'phone');
        $user = new User($id, $name, $email, $phone);
        return $user;
    }
}

## 4\. Padrão _Simple factory_

O padrão **Simple factory** Definido no livro [Head First Design Patterns](https://refactoring.guru/head-first-book). descreve uma classe que tem um método de criação com um grande condicional que, com base nos parâmetros do método, escolhe qual classe de produto instanciar e então retornar.

As pessoas costumam confundir as _simple factories_ com _factories_ em geral ou com um dos padrões de projeto de criação. Na maioria dos casos, uma simple factory é uma etapa intermediária na introdução dos padrões [Factory Method](/pt-br/design-patterns/factory-method) ou [Abstract Factory](/pt-br/design-patterns/abstract-factory).

Uma simple factory costuma ser representada por um único método em uma única classe. Com o tempo, esse método pode ficar grande demais, então você pode decidir extrair partes dele para subclasses. Depois de fazer isso algumas vezes, você pode descobrir que tudo se transformou no clássico padrão _factory method_.

A propósito, se você declarar uma simple factory como `abstract`, ela não se transforma magicamente no padrão _abstract factory_.

Aqui está um exemplo de _simple factory_:

class UserFactory {
    public static function create($type) {
        switch ($type) {
            case 'user': return new User();
            case 'customer': return new Customer();
            case 'admin': return new Admin();
            default:
                throw new Exception('Wrong user type passed.');
        }
    }
}

## 5\. Padrão _Factory Method_

O **Factory Method** Definido no livro do GoF [Design Patterns: Elements of Reusable Object-Oriented Software](https://refactoring.guru/gof-book). é um padrão de projeto de criação que fornece uma interface para criar objetos, mas permite que as subclasses alterem o tipo de objeto que será criado.

Se você tem um método de criação na classe base e subclasses que o sobrescrevem, talvez esteja diante de um factory method.

abstract class Department {
    public abstract function createEmployee($id);

    public function fire($id) {
        $employee = $this->createEmployee($id);
        $employee->paySalary();
        $employee->dismiss();
    }
}

class ITDepartment extends Department {
    public function createEmployee($id) {
        return new Programmer($id);
    }
}

class AccountingDepartment extends Department {
    public function createEmployee($id) {
        return new Accountant($id);
    }
}

## 6\. Padrão _Abstract Factory_

O **Abstract Factory** Também definido no [livro do GoF](https://refactoring.guru/gof-book). é um padrão de projeto de criação que permite produzir famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

O que são as "famílias de objetos"? Por exemplo, considere este conjunto de classes: `Transport` \+ `Engine` \+ `Controls`. Pode haver várias variantes delas:

1. `Car` \+ `CombustionEngine` \+ `SteeringWheel`
2. `Plane` \+ `JetEngine` \+ `Yoke`

Se o seu programa não trabalha com famílias de produtos, então você não precisa de uma abstract factory.

E, novamente, muita gente confunde o padrão _abstract factory_ com uma classe simple factory declarada como `abstract`. Não faça isso!

### Posfácio

Agora que você conhece a diferença, dê uma nova olhada nos padrões de projeto:

* [Factory Method](/pt-br/design-patterns/factory-method)
* [Abstract Factory](/pt-br/design-patterns/abstract-factory)
