Padrões de Design: Método Fábrica x Fábrica vs Fábrica Abstrata


183

Eu estava lendo padrões de design em um site

Lá eu li sobre Fábrica, Método de fábrica e Fábrica abstrata, mas eles são tão confusos que não estou claro sobre a definição. De acordo com definições

Fábrica - cria objetos sem expor a lógica da instanciação ao cliente e refere-se ao objeto recém-criado por meio de uma interface comum. É uma versão simplificada do Factory Method

Método de fábrica - Define uma interface para criar objetos, mas permite que as subclasses decidam qual classe instanciar e se refere ao objeto recém-criado por meio de uma interface comum.

Abstract Factory - Oferece a interface para criar uma família de objetos relacionados, sem especificar explicitamente suas classes.

Também observei os outros threads de fluxo de pilha em relação ao Abstract Factory vs Factory Method, mas os diagramas UML desenhados lá tornam meu entendimento ainda pior.

Alguém pode me dizer

  1. Como esses três padrões são diferentes um do outro?
  2. Quando usar qual?
  3. E também se possível, existem exemplos de java relacionados a esses padrões?

3
Enquanto procurava respostas para aproximadamente a mesma pergunta do OP, encontrei este artigo: De fábrica a método de fábrica . Ele fornece o insight seguindo a evolução de um projeto de amostra (o método de fábrica mencionado no título é uma das etapas evolutivas).
precisa

Respostas:


251

Todos os três tipos de fábrica fazem o mesmo: são um "construtor inteligente".

Digamos que você queira criar dois tipos de frutas: maçã e laranja.

Fábrica

O Factory é "fixo", pois você possui apenas uma implementação sem subclassificação. Nesse caso, você terá uma classe como esta:

class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

Caso de uso: Construir uma Apple ou uma Laranja é um pouco complexo demais para ser manipulado no construtor.

Método de fábrica

O método de fábrica geralmente é usado quando você tem algum processamento genérico em uma classe, mas deseja variar qual tipo de fruta você realmente usa. Assim:

abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

... então você pode reutilizar a funcionalidade comum FruitPicker.pickFruit()implementando um método de fábrica nas subclasses:

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

Fábrica abstrata

A fábrica abstrata é normalmente usada para coisas como injeção / estratégia de dependência, quando você deseja criar uma família inteira de objetos que precisam ser do "mesmo tipo" e ter algumas classes básicas comuns. Aqui está um exemplo vagamente relacionado a frutas. O caso de uso aqui é que queremos ter certeza de que não usamos acidentalmente um OrangePicker em uma Apple. Desde que obtenhamos nossa Fruit and Picker da mesma fábrica, elas serão iguais.

interface PlantFactory {

  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}

8
+1 Esta é a resposta que mais se assemelha à minha compreensão desses padrões. Adicionar exemplos de código de chamada (cliente) também ajudaria? A pergunta que me incomoda muito é: podemos dizer que o Abstract Factory Pattern é apenas a fábrica estendida com o Factory Method Pattern (se isso for verdade, estou claro sobre este tópico)?
croraf

9
Este é o exemplo que passei anos procurando.
Taztingo 16/11

Essa é uma explicação fantástica! Obrigado!
André Andrade

@ AndréAndrade Como invocar o Método de Fábrica ? Um pequeno código samle pls :) Isso esclarecerá minha dúvida sobre seu uso
Arnab Dutta

25
  1. Como esses três padrões são diferentes um do outro?

Fábrica: cria objetos sem expor a lógica da instanciação ao cliente.

Método de Fábrica: Defina uma interface para criar um objeto, mas deixe as subclasses decidirem qual classe instanciar. O método Factory permite que uma classe adie a instanciação para subclasses

Fábrica abstrata: fornece uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

O padrão AbstractFactory usa composição para delegar a responsabilidade de criar objetos para outra classe, enquanto o padrão de design do método Factory usa herança e depende da classe ou subclasse derivada para criar o objeto

  1. Quando usar qual?

Fábrica: o cliente precisa apenas de uma classe e não se importa com a implementação concreta que está recebendo.

Método de Fábrica: O cliente não sabe quais classes concretas serão necessárias para criar em tempo de execução, mas apenas deseja obter uma classe que fará o trabalho.

AbstactFactory: Quando seu sistema precisar criar várias famílias de produtos ou você desejar fornecer uma biblioteca de produtos sem expor os detalhes da implementação.

Resumo As classes de fábrica geralmente são implementadas com o método de fábrica. Os métodos de fábrica geralmente são chamados nos métodos de modelo.

  1. E também se possível, existem exemplos de java relacionados a esses padrões?

Fábrica e FactoryMethod

Intenção:

Defina uma interface para criar um objeto, mas deixe as subclasses decidirem qual classe instanciar. O Factory Factory permite que uma classe adie a instanciação para subclasses.

Diagrama UML :

insira a descrição da imagem aqui

Produto: define uma interface dos objetos que o método Factory cria.

ConcreteProduct: Implementa a interface do produto

Criador: declara o método Factory

ConcreateCreator: implementa o método Factory para retornar uma instância de um ConcreteProduct

Declaração do problema: Crie um Factory of Games usando o Factory Methods, que define a interface do jogo.

Fragmento de código:

Padrão de fábrica. Quando usar métodos de fábrica?

Comparação com outros padrões criacionais:

  1. O design começa usando o Factory Method (subclasses menos complicadas, personalizáveis ​​e proliferam) e evolui para Abstract Factory, Prototype ou Builder (mais flexível, mais complexo) à medida que o designer descobre onde é necessária mais flexibilidade

  2. Resumo As classes de fábrica geralmente são implementadas com os métodos de fábrica , mas também podem ser implementadas usando o protótipo

Referências para outras leituras: Criação de padrões de design de origem


Para o método Factory, não deve ser definida uma superclasse?
Tony Lin

21

Fábrica - classe Fábrica separada para criar objetos complexos.

Ex: classe FruitFactory para criar o objeto Fruit

class FruitFactory{

public static Fruit getFruit(){...}

}

Método de Fábrica - Em vez de toda a classe separada para fábrica, basta adicionar um método nessa classe como fábrica.

Ex:

Calendar.getInstance() (Java's Calendar)

Método abstrato de fábrica - Fábrica de Fábrica

Ex: Digamos que queremos construir uma fábrica de peças de computador. Portanto, existem vários tipos de computadores como laptop, desktop, servidor.

Portanto, para cada tipo de compilador, precisamos de fábrica. Então criamos uma fábrica de alto nível de fábricas como abaixo

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Agora, esses 3 são novamente fábricas. (Você estará lidando com o próprio PartFactory, mas, sob o capô, haverá uma implementação separada com base no que você forneceu na fábrica abstrata)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

EDIT: editado para fornecer interfaces exatas para o Abstract Factory de acordo com as objeções nos comentários.


1
A idéia por trás disso ComputerFactoryseria que você tenha uma interface de criação comum ( getScreen(); getKeyboard(); getDiskdrive(); ...), não uma interface por tipo de computador, como você sugere. Você pode sentir um problema de design se usar a mesma palavra duas vezes na mesma instrução: Laptop Factory.get Laptop Part ().
Xtofl 23/10/12

Não, não, não, não vá exatamente no próprio código. Era apenas uma anologia para a compreensão. Se você quiser um exemplo exato com interfaces, aqui está. Objetos: Interface -> ComputerPart, Implementação -> RAM, HDD, Fábrica de processadores: Interface-> PartFactory. getComputerPart (String s), Implementações -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory. Abstract Factory: ComputerType.getPartFactory ( “String s”) Uso:.. Nova ComputerType () getFactory ( “Laptop”) getComputerPart ( “RAM”)
Ravi K

2
Atualizei a resposta para cuidar da sua preocupação. Na verdade, a fábrica abstrata nada mais é do que apenas uma fábrica. Dei um exemplo anterior apenas para referência (assumindo que os leitores cuidarão das interfaces durante a implementação real). Ainda obrigado por notificar. É sempre bom melhorar. :)
Ravi K

Não, abstract Factorynão é uma fábrica de fábrica ... É um abstract classou interfacecapaz de criar objetos que serão implementados / ampliados com diferentes fábricas de concreto. Veja a resposta aceita para obter detalhes do código. E remova ou edite sua resposta de acordo.
Julien__

Gosto da explicação do método de fábrica, que é conciso o suficiente para revelar por que esse nome é chamado. Nesse padrão, a fábrica é o método, NÃO a classe que geralmente não é um utilitário auxiliar que agrupa métodos de instanciação, mas é significativo por si só. Outras respostas mais elaboradas, infelizmente, não entenderam esse ponto.
wlnirvana 13/03

11

Todo padrão de design prospera para ajudar a garantir que o código escrito e funcional não seja tocado. Todos sabemos que, uma vez que tocamos no código de trabalho, há defeitos nos fluxos de trabalho existentes e muito mais testes precisam ser feitos para garantir que não quebremos nada.

Um padrão de fábrica cria objetos com base em critérios de entrada, garantindo assim que você não precise escrever código como se isso criasse esse tipo de objeto ou esse tipo de objeto. Um bom exemplo disso é um site de viagens. Um site de viagens pode fornecer viagens (voo, trem, ônibus) ou / e fornecer hotéis ou pacotes de atração turística. Agora, quando um usuário seleciona a seguir, o site precisa decidir quais objetos ele precisa criar. Deve criar apenas o objeto de viagem ou hotel também.

Agora, se você pensa em adicionar outro site ao seu portfólio e acredita que o mesmo núcleo seja usado, por exemplo, um site de carpooling, que agora pesquisa táxis e faz pagamentos on-line, você pode usar uma fábrica abstrata em seu núcleo. Dessa forma, você pode simplesmente instalar mais uma fábrica de táxis e estufas.

As duas fábricas não têm nada a ver uma com a outra, por isso é um bom design para mantê-las em diferentes fábricas.

Espero que isso esteja claro agora. Estude o site novamente, mantendo este exemplo em mente, espero que ajude. E eu realmente espero ter representado os padrões corretamente :).


3

Para esta resposta, refiro-me ao livro "Gang of Four".

Não definições de "Fábrica", "Fábrica simples" ou "Fábrica virtual" no livro. Normalmente, quando as pessoas estão falando sobre o padrão "Factory", podem estar falando sobre algo que cria um objeto específico de uma classe (mas não o padrão "construtor"); eles podem ou não se referir aos padrões "Factory Method" ou "Abstract Factory". Qualquer um pode implementar "Factory" como ele não o fará, porque não é um termo formal (lembre-se de que algumas pessoas \ empresas \ comunidades podem ter seu próprio vocabulário).

O livro contém apenas definições para "Abstract Factory" e "Factory Method".

Aqui estão as definições do livro e uma breve explicação de por que ambos podem ser tão confusos. Eu omito exemplos de código porque você pode encontrá-los em outras respostas:

Método de fábrica (GOF) : defina uma interface para criar um objeto, mas deixe as subclasses decidirem qual classe instanciar. O Método de Fábrica permite que uma classe adie a instanciação para subclasses.

Fábrica abstrata (GOF) : forneça uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

Fonte de confusão : Geralmente, pode-se chamar uma classe usada no padrão "Factory Method" como "Factory". Esta classe é abstrata por definição. Por isso é fácil chamar essa classe de "Fábrica Abstrata". Mas é apenas o nome da turma; você não deve confundi-lo com o padrão "Abstract Factory" (nome da classe! = nome do padrão). O padrão "Abstract Factory" é diferente - ele não usa uma classe abstrata; define uma interface (não necessariamente uma interface de linguagem de programação) para criar partes de um objeto maior ou objetos que são relacionados entre si ou que devem ser criados de uma maneira específica.


2
AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Usando o Método de Fábrica, o usuário pode criar A1 ou A2 de AbstractProductA.

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

Mas Abstract Factory com mais de um método de fábrica (por exemplo: 2 métodos de fábrica), usando esses métodos de fábrica, ele criará o conjunto de objetos / objetos relacionados. Usando Abstract Factory, o usuário pode criar objetos A1, B1 de AbstractProductA, AbstractProductB


0

Ninguém citou o livro original Design Patterns: Elements of Reusable Oriented Object Software , que fornece a resposta nos dois primeiros parágrafos da seção "Discussão sobre padrões criacionais" (grifo meu):

Existem duas maneiras comuns de parametrizar um sistema pelas classes de objetos que ele cria. Uma maneira é subclassificar a classe que cria os objetos; isso corresponde ao uso do padrão Factory Method (107). A principal desvantagem dessa abordagem é que ela pode exigir uma nova subclasse apenas para alterar a classe do produto. Tais mudanças podem ocorrer em cascata. Por exemplo, quando o criador do produto é ele próprio criado por um método de fábrica, você também deve substituir o criador.

A outra maneira de parametrizar um sistema depende mais da composição do objeto : defina um objeto responsável por conhecer a classe dos objetos do produto e faça dele um parâmetro do sistema. Esse é um aspecto essencial dos padrões Abstract Factory (87), Builder (97) e Prototype (117). Todos os três envolvem a criação de um novo "objeto de fábrica" ​​cuja responsabilidade é criar objetos de produto. Abstract Factory possui o objeto factory produzindo objetos de várias classes. O Builder possui o objeto de fábrica que constrói um produto complexo de forma incremental usando um protocolo complexo correspondente. Prototype possui o objeto de fábrica que constrói um produto, copiando um objeto de protótipo. Nesse caso, o objeto de fábrica e o protótipo são o mesmo objeto, porque o protótipo é responsável pela devolução do produto.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.