1. Factory Method (Método Fábrica)

1.1. Definição

📘"Fornece uma interface para criar um objeto, mas permite às subclasses decidirem qual tipo de objeto instanciar." [UCPP]

1.2. Aplicabilidade

Podemos utilizar o padrão quando:

  • uma classe precisa utilizar um tipo de objeto, mas ela não tem como decidir qual tipo concreto utilizar, pois tal lógica é definida por subclasses;

  • cada subclasse tem uma lógica diferente para a criação dos objetos (juntar estas lógicas na superclasse tornaria o código extenso e confuso);

  • novas subclasses puderem ser introduzidas a qualquer momento com diferentes lógicas;

  • você não conhece todos os tipos concretos de objetos que podem ser criados;

  • é necessário criar objetos por meio de composição, cada objeto instanciado é um todo composto por diferentes partes, tais partes devem ser escolhidas de acordo com o todo.

1.3. Modelagem

factory method
Figure 1. Modelagem do Factory Method

TipoAbstrato é uma interface ou classe abstrata/super classe que representa o tipo dos objetos que a fábrica pode criar. As classes TipoConcreto1 até TipoConcretoN representam os tipos concretos que podem ser instanciados de fato pela fábrica. CriadorAbstrato representa a implementação base da fábrica. Ela pode ter quaisquer métodos que forem necessários, incluindo um método abstrato newObject() que deverá ser implementados pelos criadores concretos.

A classe CriadorAbstrato normalmente terá um método que chamará o newObject() para usar o objeto criado. Neste exemplo, tal método é o useObject(), mas em uma implementação real, o método deve ter um nome de acordo com o problema sendo resolvido.

Diferente da Simple Factory:

  • a lógica que define qual objeto será instanciado não é centralizada em uma classe, mas sim nas subclasses de CriadorAbstrato;

  • logo, o método newObject() é abstrato, pois as subclasses de CriadorAbstrato é que o implementarão.

  • tal método não deve ser estático se ele for usado por outros métodos da classe (como é o caso deste modelo);

Cada subclasse de CriadorAbstrato é que definirá a lógica para a instanciação do objeto representado por TipoAbstrato. Para a Simple Factory não existem subclasses.

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

1.4. Princípios utilizados

1.4.1. Single-Responsitility Principle

Com o Single-Responsitility Principle (SRP), a classe CriadorAbstrato de fato não cria os objetos, apenas define um método que as filhas devem implementar para isto. Ela apenas usará os objetos criados. Cada subclasse terá a responsabilidade de criar tais objetos.

1.4.2. Open-Closed Principle

Com o Open/Closed Principle (OCP), separamos as partes que mudam, i.e. a lógica de criação de objetos, de dentro da classe que utiliza tais objetos. Isto torna a classe que utiliza a factory "aberta para extensão e fechada para modificação".

1.4.3. Programar para uma "interface" não uma implementação

Programar para uma "interface" não uma implementação (GoF) indica que devemos declar variáveis com tipos abstratos (TipoAbstrato) e usar tipos concretos apenas na instanciação (SubTipo1 …​ SubTipoN).

1.4.4. Dependency Inversion Principle (DIP)

Ao aplicar o Dependency Inversion Principle (DIP), a classe CriadorAbstrato não depende de tipos concretos, mas sim de tipos abstratos (interfaces ou classes abstratas). Ela não precisa saber quais são os tipos concretos existentes.

1.5. Remodelando o projeto Exportador Produto com a Simple Factory

Antes de implementarmos o padrão Factory Method, precisamos voltar ao projeto anterior, para fazer algumas alterações considerando um novo cenário.

Os detalhes são fornecidos no projeto exportador-problematico.

1.6. Exemplos

Podemos utilizar o Factory Method para encapsular a instanciação de colunas de uma tabela em formato específico, baseado no projeto exportador-simple-factory-reflection. Implemente o projeto seguindo a modelagem abaixo:

factory method exportador
Figure 2. Factory Method para a instanciação de colunas de uma tabela em formato específico

O código fonte do projeto está disponível aqui (zip).

1.7. Detalhes de Implementação

xxxxxxxxxxxx

2. Problemas da NÃO utilização do padrão

Veja o projeto exportador-problematico (zip). Ele é uma implementação do exportador de dados sem utilizar o padrão Factory Method, seguindo a modelagem do diagrama abaixo:

no factory method exportador produtos
Figure 3. Exportador de dados que NÃO usa o padrão Factory Method

3. Padrões Relacionados

Padrões que possuem similaridades ou podem ser usados em conjunto: