Outros nomes conhecidos: Construtor virtual
Defina uma (interface ou classe abstrata) para o "Produto", crie as diversas implementações concretas deste "produto", então defina um ou mais métodos factories, para retornar o objeto concreto desejado.
- Importante lembrar as seguintes coisas básicas de OO:
-
- É regra básica de OO, que os tipos definidos devem ser sempre os mais abstratos possíveis. Pois você deve desenvolver toda a lógica da aplicação dependendo desses tipos abstratos.
-
- Por isso que o método factory é apenas um coadjuvante para participar da construção de toda a regra de negócios da aplicação.
-
- Por estes motivos devemos decidir o melhor lugar e forma de criar o método factory, onde faça mais sentido na participação da construção das lógicas subjacentes.
Formas de criar objetos, de maneira "transparente" para a lógica do negócio.
- Problema 0: Quando você tem uma classe com diversos métodos, e todos eles criam objetos semelhantes com configurações diferentes, você acaba encontrando muito código comum entre os métodos.
- Problema 1: Geralmente uma classe com um grande bloco de IFs que só tende a crescer, as vezes encapsulado em um método. Isso caracteriza um "problema chamado" simple factory, que nada tem haver com Factory Method ou qualquer padrão de projeto.
- Problema 2: Imagine que você tem uma Classe que faz integração com um serviço externo, e essa classe possui vários métodos, cada método representa uma nova comunicação com esse serviço externo, para cada nova comunicação um novo método é sempre criado.
- Cria-se uma interface ou classe abstrata com o comportamento comum do produto.
- Faz as diversas implementações.
- Um método factory é criado que determina qual classe concreta será instanciada.
- Este método factory pode ser implementado dentro da classe Cliente ou em uma classe específica para isso. Esse método factory pode ainda ser granulado, ou segmentado em grupos, dependendo da complexidade, pode ser um método factory para cada classe produto.
Simples, onde a factory fica na própria classe cliente, como acima.- Quando a factory a ser criada é pequena e simples, e será usada somente naquela classe cliente.
classDiagram
Client ..> Iphone
Client ..> Iphone11
Client ..> IphoneX
Client ..> IphonePro
Client: +factory(Class<?> type) Iphone
Iphone <|-- Iphone11
Iphone <|-- IphoneX
Iphone <|-- IphonePro
class Iphone{
<<interface>>
+create() Iphone
}
class Iphone11{
+create() Iphone
}
class IphoneX{
+create() Iphone
}
class IphonePro{
+create() Iphone
}
..> Dependencia, —|> Herança [About Mermaid]
- Simples, onde a factory fica em classe separada.
- Quando a factory a ser criada ficou grande, e/ou será usado por vários clientes.
classDiagram
client ..> IphoneFactory
client ..> Iphone
IphoneFactory ..> Iphone
IphoneFactory ..> IphoneX
IphoneFactory ..> IphoneXSMax
IphoneFactory ..> Iphone11
IphoneFactory ..> Iphone11Pro
Iphone <|-- IphoneX
Iphone <|-- IphoneXSMax
Iphone <|-- Iphone11
Iphone <|-- Iphone11Pro
IphoneFactory: factory(Class<?> type) Iphone
class Iphone{
<<interface>>
+create() Iphone
}
IphoneX: +create() Iphone
IphoneXSMax: +create() Iphone
Iphone11: +create() Iphone
Iphone11Pro: +create() Iphone
- Médio, se a factory crescer demais, podemos segmenta-la em grupos.
- Quando se faz sentido criar uma classe factory para cada grupo das classes concretas relacionadas.
classDiagram
client ..> IphoneFactory
client ..> IphoneXFactory
client ..> Iphone11Factory
client ..> Iphone
IphoneFactory <|-- IphoneXFactory
IphoneFactory <|-- Iphone11Factory
IphoneXFactory ..> IphoneX
IphoneXFactory ..> IphoneXSMax
Iphone11Factory ..> Iphone11
Iphone11Factory ..> Iphone11Pro
Iphone <|-- IphoneX
Iphone <|-- IphoneXSMax
Iphone <|-- Iphone11
Iphone <|-- Iphone11Pro
class IphoneFactory{
<<abstract>>
#factory(Type type) Iphone
}
IphoneXFactory: factory(Type type) Iphone
Iphone11Factory: factory(Type type) Iphone
class Iphone{
<<interface>>
+create() Iphone
}
IphoneX: +create() Iphone
IphoneXSMax: +create() Iphone
Iphone11: +create() Iphone
Iphone11Pro: +create() Iphone
- Complexo, onde há uma classe factory para cada implementação concreta criada.
- Quando a construção da factory para cada classe concreta é grande e complexa demais.
classDiagram
Client ..> DBFactory
Client ..> OracleDBFactory
Client ..> PostgresDBFactory
Client ..> DB
DBFactory <|-- OracleDBFactory
DBFactory <|-- PostgresDBFactory
OracleDBFactory ..> OracleDB
PostgresDBFactory ..> PostgresDB
DB <|-- OracleDB
DB <|-- PostgresDB
class DB{
<<interface>>
}
class DBFactory{
<<abstract>>
}
Obs.: O Factory Method é um padrão de projeto que se baseia em herança. Se você torná-lo estático, você não pode mais estendê-lo em subclasses, que é contrário ao propósito do padrão.
No padrão acima, abstraímos apenas um produto, quando precisamos abstrair mais de um produto, partimos para o próximo padrão, Fábrica Abstrata.
Permite que você produza famílias de objetos relacionados sem ter que especificar suas classes concretas.
...
- Problema 0: Sua lógica de negócios precisa trabalhar com diversas famílias de produtos relacionados.
- Problema 1: Quando você tem uma classe com um conjunto de métodos fábrica que desfoquem sua responsabilidade principal.
- Defini-se uma interface ou classe abstrata para cada produto.
- Faz as implementações das diversas variantes de cada produto.
- Defina a interface para a abstract factory, com um método para cada produto da interface de produtos.
- Faz as implementações por familia de produtos.
- No inicio da execução da lógica, cria-se a factory concreta a ser usada no processo. A partir daí segue trabalhando com os tipos abstratos da factory e dos produtos.
Construir objetos complexos passo a passo.
...
- Problema 0: Pode tentar resolver criando uma classe base, e várias subclasses dela. Isso gera muitas sub-classes.
- Problema 1: Tentativa de resolver com uma única classe, que possua um construtor com todos os parametros possíveis. Isso gerará instaciações confusas e com muitos nulls.
- Problema 2: Tentativa de resolver com uma única classe, com vários construtores, um para cada caso. Isso gerará uma quantidade grande de construtores.
- Extraia o código de construção do objeto para fora de sua própria classe.
- Mova para objetos separados chamados builders.
- O objeto não deve ser acessado enquanto está sendo construído.
- Para seguencias ordenadas da construção, podemos colocar em outra classe Diretor.
-
Simples, o builder é criado dentro da própria classe produto.
-
Médio, onde tempos produtos que podem ser relacionados logicamente e podemos criar uma interface builder comum a eles.

Outros nomes conhecidos: Clone
Copiar objetos existentes sem fazer seu código ficar dependente de suas classes.
...
- Problema 0: ..
- Crie uma interface com um método clone.
- Toda classe que deva ser clonavel, deve implementar essa interface.
============
Construir objetos complexos passo a passo.
...
- Problema 0: Pode tentar resolver criando uma classe base, e várias subclasses dela. Isso gera muitas sub-classes.
- Problema 1: Tentativa de resolver com uma única classe, que possua um construtor com todos os parametros possíveis. Isso gerará instaciações confusas e com muitos nulls.
- Problema 2: Tentativa de resolver com uma única classe, com vários construtores, um para cada caso. Isso gerará uma quantidade grande de construtores.
- Extraia o código de construção do objeto para fora de sua própria classe.
- Mova para objetos separados chamados builders.
- O objeto não deve ser acessado enquanto está sendo construído.
- Para seguencias ordenadas da construção, podemos colocar em outra classe Diretor.
-
Simples, o builder é criado dentro da própria classe produto.
-
Médio, onde tempos produtos que podem ser relacionados logicamente e podemos criar uma interface builder comum a eles.

Garante a geração de uma única instância de uma classe em uma aplicação. Se seu ambiente for multi-thread, você precisará controlar este caso.
- Problema 0: Controlar o acesso a algum recurso compartilhado, através de uma única instância. Existem variações desse problema, onde deve haver um número limitado de instâncias.
- Torne os construtores privados e crie um método estático que retorne a instancia única.
- Não implemente a lógica que deveria ficar no método "getInstance()" no construtor da classe, pois quando alguém usa o new, ele tem a certeza de estar gerando uma nova instância, o que acabará não ocorrendo.
Outros nomes conhecidos: Wrapper
Permite que interface incompatíveis colaborem.
Converter a interface de um objeto para que outro objeto possa entendê-lo.
- Problema 0: Apis com protocolos de comunicações diferentes, XML to JSON.
- Problema 1: Quando você quiser encaixar um pino quadrado em um buraco redondo, rs.
- Criar ou obter a interface de comunição com o cliente que deseja-se comunicar.
- Criar a classe Adapter para implements ou extends o contrato acima.
- Adicionar o objeto "incompatível" como propriedade da classe adapter, normalmente você recebe a instancia dele via construtor.
- Cumprir a implementação do contrato, se utilizando do objeto incompativel para realizar o de-para da comunicação.
Permite que você divida, uma classe grande ou uma hieraquia de classes horizontais (tentando estender as classes em duas dimensões diferentes), em hieraquias separadas idependentes. Apenas extraindo abstrações e realizando suas diversas implementações. Mantenha a classe principal e troque as demais de herança por composição, essas tais referencias irão agir como uma ponte.
...
- Problema 0: Eliminar heranças horizontais.
- Problema 1: Quebrar uma classe grande em pedaços menores.
Fontes:
Readme.md: https://raullesteves.medium.com/github-como-fazer-um-readme-md-bonit%C3%A3o-c85c8f154f8

