Quais são as diferenças entre os padrões de design Abstract Factory e Factory?

455

Sei que existem muitos posts sobre as diferenças entre esses dois padrões, mas há algumas coisas que não consigo encontrar.

Pelo que tenho lido, vejo que o padrão do método de fábrica permite definir como criar um único produto concreto, mas ocultando a implementação do cliente, pois eles verão um produto genérico. Minha primeira pergunta é sobre a fábrica abstrata. Seu papel é permitir que você crie famílias de objetos concretos (que podem depender de qual fábrica específica você usa), em vez de apenas um único objeto concreto? A fábrica abstrata retorna apenas um objeto muito grande ou muitos objetos, dependendo de quais métodos você chama?

Minhas duas perguntas finais são sobre uma única citação que não consigo entender completamente que já vi em vários lugares:

Uma diferença entre os dois é que, com o padrão Abstract Factory, uma classe delega a responsabilidade da instanciação de objeto para outro objeto por meio de composição, enquanto o padrão Factory Method usa herança e depende de uma subclasse para lidar com a instanciação de objeto desejada.

Meu entendimento é que o padrão do método de fábrica possui uma interface Creator que fará com que o ConcreteCreator se encarregue de saber qual produto concreto instanciar. É isso o que significa usar herança para manipular instanciação de objeto?

Agora, com relação a essa citação, como exatamente o padrão Abstract Factory delega a responsabilidade da instanciação do objeto para outro objeto via composição? O que isto significa? Parece que o padrão Abstract Factory também usa herança para fazer o processo de construção também aos meus olhos, mas, novamente, ainda estou aprendendo sobre esses padrões.

Qualquer ajuda, especialmente com a última pergunta, seria muito apreciada.

Silverbolt
fonte
Ver "como a instância foi criada" do ponto de vista do cliente ajudaria a entender a cotação.
Karthik Bose
@nawfal, as respostas nesse tópico são terríveis.
jaco0646

Respostas:

494

A diferença entre os dois

A principal diferença entre um "método de fábrica" ​​e uma "fábrica abstrata" é que o método de fábrica é um método único e uma fábrica abstrata é um objeto. Acho que muitas pessoas confundem esses dois termos e começam a usá-los de forma intercambiável. Lembro que tive dificuldade em encontrar exatamente qual era a diferença quando as aprendi.

Como o método factory é apenas um método, ele pode ser substituído em uma subclasse, daí a segunda metade da sua citação:

... o padrão Factory Method usa herança e depende de uma subclasse para manipular a instanciação de objeto desejada.

A cotação assume que um objeto está chamando seu próprio método de fábrica aqui. Portanto, a única coisa que poderia alterar o valor de retorno seria uma subclasse.

A fábrica abstrata é um objeto que possui vários métodos de fábrica. Olhando para a primeira metade da sua citação:

... com o padrão Abstract Factory, uma classe delega a responsabilidade da instanciação de objeto para outro objeto via composição ...

O que eles estão dizendo é que existe um objeto A, que quer fazer um objeto Foo. Em vez de criar o objeto Foo em si (por exemplo, com um método de fábrica), ele obterá um objeto diferente (a fábrica abstrata) para criar o objeto Foo.

Exemplos de código

Para mostrar a diferença, aqui está um método de fábrica em uso:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

E aqui está uma fábrica abstrata em uso:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here
Tom Dalling
fonte
15
Esta é uma ótima explicação. Mas, qual é a parte mais importante é deixada sem resposta, e é isso: quando usar um e quando o outro padrão?
croraf
11
Não tenho certeza se isso está correto. Certamente o Factory Method é um padrão de design com o nome dos métodos de fábrica, mas envolve a estrutura e a herança da classe. Não é um método único.
Aviv Cohn
2
Portanto, é correto dizer: o método Factory pode ser um método em todas as classes regulares com propósitos diferentes. Mas a Abstract Factory é uma classe / objeto usado por um cliente e é SOMENTE responsável por criar alguns produtos em uma família?
Hieu Nguyen
Seu uso da palavra "Super" em "SuperFoo" significa apenas um caso especial de Foo, ou realmente significa superclasse? Como eu assumi, deve ser uma subclasse.
dahui 14/09/16
@dahui Sim, é uma subclasse. Eu mudei SpecialFoopara ficar mais claro.
Tom Dalling
125

Abstract factory cria uma classe base com métodos abstratos que definem métodos para os objetos que devem ser criados. Cada classe de fábrica que deriva da classe base pode criar sua própria implementação de cada tipo de objeto.

insira a descrição da imagem aqui

O método Factory é apenas um método simples usado para criar objetos em uma classe. Geralmente é adicionado à raiz agregada (a Orderclasse tem um método chamado CreateOrderLine)

insira a descrição da imagem aqui

Fábrica abstrata

No exemplo abaixo, projetamos uma interface para poder dissociar a criação de filas de um sistema de mensagens e, portanto, criar implementações para diferentes sistemas de filas sem precisar alterar a base de código.

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

Método de fábrica

O problema nos servidores HTTP é que sempre precisamos de uma resposta para cada solicitação.

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

Sem o método de fábrica, os usuários do servidor HTTP (ou seja, programadores) seriam forçados a usar classes específicas de implementação que anulam o objetivo da IHttpRequestinterface.

Portanto, introduzimos o método factory para que a criação da classe de resposta também seja abstraída.

Sumário

A diferença é que o objetivo pretendido da classe que contém um método factory não é criar objetos , enquanto uma fábrica abstrata deve ser usada apenas para criar objetos.

Deve-se tomar cuidado ao usar métodos de fábrica, pois é fácil quebrar o LSP ( princípio de substituição de Liskov ) ao criar objetos.

jgauffin
fonte
3
Por que precisamos de um produto concreto?
Andrew S
60
Porque ninguém quer investir em idéias.
jgauffin
4
A Abstract Factory deve criar mais do que apenas Button()para criar uma "família de produtos relacionados". Por exemplo, o exemplo canônico do GoF cria ScrollBar()e Window(). A vantagem é que a Abstract Factory pode aplicar um tema comum em seus múltiplos produtos.
jaco0646
Jaco está certo. Considere que os dois diagramas UML são essencialmente os mesmos (ao lado do UML Abstract Factory estar errado). Nos dois casos, o cliente está chamando um método de fábrica para criar um único produto.
cobby
1
@ Andrews: Para responder à sua pergunta. Se não precisarmos ter diferentes produtos concretos (classes) para a mesma abstração (interface), provavelmente precisaremos do padrão do construtor e não do padrão da fábrica. (melhor tarde do que nunca;))
jgauffin
95

As diferenças entre os padrões de design AbstractFactory e Factory são as seguintes:

  • O método Factory é usado para criar apenas um produto, mas o Abstract Factory trata da criação de famílias de produtos relacionados ou dependentes.
  • O padrão Factory Method expõe um método ao cliente para criar o objeto, enquanto no Abstract Factory ele expõe uma família de objetos relacionados que podem consistir nesses métodos de Factory.
  • O padrão Factory Method oculta a construção de um único objeto, enquanto o Abstract Factory oculta a construção de uma família de objetos relacionados. Fábricas abstratas geralmente são implementadas usando (um conjunto de) métodos de fábrica.
  • Resumo O padrão de fábrica usa a composição para delegar a responsabilidade de criar um objeto para outra classe, enquanto o padrão de design do Método de Fábrica usa herança e depende de uma classe ou subclasse derivada para criar um objeto.
  • A idéia por trás do padrão Factory Method é que ele permite o caso em que um 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 enquanto o padrão Abstract Factory estiver é melhor utilizado quando o sistema precisa criar várias famílias de produtos ou você deseja fornecer uma biblioteca de produtos sem expor os detalhes da implementação.

Implementação de padrão de método de fábrica: Método de fábrica UML

Implementação abstrata de padrão de fábrica:

Fábrica abstrata UML

Vibha Sanskrityayan
fonte
13
Mmm, não tenho certeza sobre o exemplo abstrato de fábrica. Eu acho que a fábrica de formas e cores deve implementar os mesmos métodos. Mas se estou certo, a amostra não faz sentido.
Joaquin Iurchuk 15/11/2015
4
Os marcadores estão corretos; no entanto, ambos os diagramas estão completamente errados e muito enganadores. Veja o diagrama abaixo em @Trying para obter um modelo preciso da Abstract Factory.
jaco0646
1
Eu tenho que concordar que os dois diagramas são muito enganosos. Eu os vi no site tutorialspoint e, para ser sincero, não concordo 100% com eles. Porém, as descrições parecem boas
SoftwareDeveloper
Isso é muito enganador.
precisa saber é o seguinte
Mais de 50 votos positivos e os diagramas estão muito errados. Prova de que você não pode confiar em muitas respostas de padrões de design no SO.
Fuhrmanator
27

A principal diferença entre Abstract Factory e Factory Method é que Abstract Factory é implementado pela Composition ; mas o Método de Fábrica é implementado pela Herança .

Sim, você leu corretamente: a principal diferença entre esses dois padrões é o antigo debate sobre composição versus herança .

Os diagramas UML podem ser encontrados no livro (GoF). Desejo fornecer exemplos de código, porque acho que a combinação dos exemplos das duas principais respostas neste segmento fornecerá uma demonstração melhor do que qualquer uma das respostas. Além disso, usei a terminologia do livro nos nomes de classe e método.

Fábrica abstrata

  1. O ponto mais importante a entender aqui é que a fábrica abstrata é injetada no cliente. É por isso que dizemos que o Abstract Factory é implementado pela Composition. Freqüentemente, uma estrutura de injeção de dependência executaria essa tarefa; mas uma estrutura não é necessária para DI.
  2. O segundo ponto crítico é que as fábricas de concreto aqui não são implementações de Método de Fábrica! O código de exemplo para o Método de fábrica é mostrado mais abaixo.
  3. E, finalmente, o terceiro ponto a ser observado é o relacionamento entre os produtos: nesse caso, as filas de saída e resposta. Uma fábrica de concreto produz filas do Azure, a outra MSMQ. O GoF refere-se a esse relacionamento de produto como uma "família" e é importante estar ciente de que a família neste caso não significa hierarquia de classes.
public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

Método de fábrica

  1. O ponto mais importante a entender aqui é que o ConcreteCreator é o cliente. Em outras palavras, o cliente é uma subclasse cujo pai define o factoryMethod(). É por isso que dizemos que o Método de Fábrica é implementado pela Herança.
  2. O segundo ponto crítico é lembrar que o Padrão de Método de Fábrica nada mais é do que uma especialização do Padrão de Método de Modelo. Os dois padrões compartilham uma estrutura idêntica. Eles diferem apenas em propósito. O Método de Fábrica é criacional (cria algo), enquanto o Método de Modelo é comportamental (calcula algo).
  3. E, finalmente, o terceiro ponto a ser observado é que a Creatorclasse (pai) invoca a sua própria factoryMethod(). Se removermos anOperation()da classe pai, deixando apenas um único método para trás, ele não será mais o padrão Factory Method. Em outras palavras, o Método de Fábrica não pode ser implementado com menos de dois métodos na classe pai; e um deve invocar o outro.
public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

Misc. E padrões de fábricas diversas

Esteja ciente de que, embora o GoF defina dois padrões de fábrica diferentes, esses não são os únicos padrões de fábrica existentes. Eles não são necessariamente os padrões de fábrica mais usados. Um terceiro exemplo famoso é o Static Factory Pattern de Josh Bloch da Effective Java. O livro Head First Design Patterns inclui ainda outro padrão que eles chamam de Simple Factory.

Não caia na armadilha de assumir que todos os padrões de fábrica devem corresponder a um do GoF.

jaco0646
fonte
3
Resposta ótima e muito clara, com base em bons exemplos, os melhores neste tópico IMO.
21419 Luke Duda
Ótima explicação. +1 para o método Factory deve chamar seu ponto abstrato do método factory. Com esse ponto, fica muito claro, sem entender esse ponto: se o método de fábrica não for invocado por ele próprio, ele será usado por alguma outra classe que o comporá e suas subclasses serão injetadas, se transformará em fábrica abstrata , diferença torna-se menos claro se o ponto que o método de fábrica abstrata deve ser invocado pela própria fábrica como padrão template Method não é compreendido
nits.kk
Mais uma pergunta. factoryMethod()Sempre deve ser o protected método no padrão "Factory Method"? (Eu acho que sim)
Yaroslav Fedoruk
1
@YaroslavFedoruk, o livro do GoF permite publicmétodos de fábrica, e o método nem precisa ser abstract; mas o ponto crítico é que o método é destinado à herança; portanto, não pode (por exemplo) ser staticou final. Eu criei o método protectede abstractaqui para destacar a extensibilidade (necessária).
precisa saber é o seguinte
@ nits.kk, você pode estar interessado em uma resposta relacionada .
jaco0646 03/09/19
26

Resumo O Factory é uma interface para a criação de produtos relacionados, mas o Factory Method é apenas um método. Resumo O Factory pode ser implementado por vários métodos de Factory.

Fábrica abstrata UML

Tentando
fonte
10
Você já postou a mesma resposta aqui . Se você acha que essa pergunta é semelhante, sinalize-a como duplicada.
Ja͢ck
11

Considere este exemplo para facilitar o entendimento.

O que as empresas de telecomunicações fornecem? Banda larga, linha telefônica e celular, por exemplo, e você é solicitado a criar um aplicativo para oferecer seus produtos a seus clientes.

Geralmente, o que você faria aqui é criar produtos, como banda larga, linha telefônica e celular, através do seu Método de Fábrica, onde você sabe quais propriedades possui para esses produtos e é bem direto.

Agora, a empresa deseja oferecer a seus clientes um pacote de seus produtos, como banda larga, linha telefônica e celular, e aqui vem a Abstract Factory para jogar.

A Abstract Factory é, em outras palavras, a composição de outras fábricas responsáveis ​​pela criação de seus próprios produtos e a Abstract Factory sabe como colocar esses produtos em mais significado em relação às suas próprias responsabilidades.

Nesse caso, o BundleFactoryé a Fábrica abstrata BroadbandFactory, PhonelineFactorye MobileFactoryé o Factory. Para simplificar mais, essas fábricas terão o Método de Fábrica para inicializar os produtos individuais.

Veja o exemplo de código abaixo:

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

Espero que isto ajude.

Abdul Munim
fonte
1
Não há staticmétodos no padrão de fábrica GoF. Isto está errado.
precisa saber é o seguinte
5

Exemplo da vida real. (Fácil de lembrar)

Fábrica

Imagine que você está construindo uma casa e se aproxima de um carpinteiro em busca de uma porta. Você dá a medida da porta e seus requisitos, e ele construirá uma porta para você. Nesse caso, o carpinteiro é uma fábrica de portas. Suas especificações são entradas para a fábrica e a porta é a saída ou produto da fábrica.

Fábrica abstrata

Agora, considere o mesmo exemplo da porta. Você pode ir a um carpinteiro ou a uma loja de portas de plástico ou a uma loja de PVC. Todos eles são fábricas de portas. Com base na situação, você decide que tipo de fábrica precisa abordar. Isto é como uma fábrica abstrata.

Expliquei aqui o padrão do método Factory e o padrão abstrato de fábrica, começando por não usá-los, explicando problemas e resolvendo problemas usando os padrões acima https://github.com/vikramnagineni/Design-Patterns/tree/master

Vikram Babu Nagineni
fonte
3

Vamos deixar claro que na maioria das vezes no código de produção, usamos o padrão abstrato de fábrica porque a classe A é programada com a interface B. E A precisa criar instâncias de B. Portanto, A precisa ter um objeto de fábrica para produzir instâncias de B Portanto, A não depende de nenhuma instância concreta de B. Espero que ajude.

Adrian Liu
fonte
3

Entenda as diferenças nas motivações:

Suponha que você esteja construindo uma ferramenta na qual tenha objetos e uma implementação concreta das inter-relações dos objetos. Como você prevê variações nos objetos, criou um indireto atribuindo a responsabilidade de criar variantes dos objetos para outro objeto ( chamamos de fábrica abstrata ). Essa abstração encontra um grande benefício, pois você prevê futuras extensões que precisam de variantes desses objetos.

Outra motivação bastante intrigante nessa linha de pensamento é um caso em que todos ou nenhum dos objetos de todo o grupo terá uma variante correspondente. Com base em algumas condições, qualquer uma das variantes será usada e, em cada caso, todos os objetos devem ser da mesma variante. Isso pode ser um pouco contra-intuitivo de entender, pois costumamos pensar que - desde que as variantes de um objeto sigam um contrato uniforme comum ( interface em sentido mais amplo ), o código de implementação concreto nunca deve quebrar. O fato intrigante aqui é que, nem sempre isso é verdade, especialmente quando o comportamento esperado não pode ser modelado por um contrato de programação.

Um simples ( emprestando a idéia do GoF ) é qualquer aplicativo GUI, como um monitor virtual que simula a aparência de MS ou Mac ou Fedora OS. Aqui, por exemplo, quando todos os objetos de widget, como janela, botão, etc. possuem variante MS, exceto uma barra de rolagem derivada da variante MAC, o objetivo da ferramenta falha muito.

Esses casos acima formam a necessidade fundamental do Abstract Factory Pattern .

Por outro lado, imagine que você esteja escrevendo uma estrutura para que muitas pessoas possam criar várias ferramentas ( como a dos exemplos acima ) usando sua estrutura. Pela própria idéia de uma estrutura, você não precisa, embora não possa usar objetos concretos em sua lógica. Você prefere colocar alguns contratos de alto nível entre vários objetos e como eles interagem. Enquanto você ( como desenvolvedor de estrutura ) permanece em um nível muito abstrato, cada construtor da ferramenta é forçado a seguir suas construções de estrutura. No entanto, eles ( os construtores de ferramentas ) têm a liberdade de decidir qual objeto será construído e como todos os objetos que eles criarão interagirão. Diferentemente do caso anterior ( do Abstract Factory Pattern ), você ( como criador da estrutura) não precisa trabalhar com objetos concretos nesse caso; e, em vez disso, pode permanecer no nível de contrato dos objetos. Além disso, diferentemente da segunda parte das motivações anteriores, você ou os fabricantes de ferramentas nunca têm a situação de misturar objetos de variantes. Aqui, enquanto o código da estrutura permanece no nível do contrato, todo construtor de ferramentas fica restrito ( pela natureza do caso ) a usar seus próprios objetos. Neste caso, as criações de objetos são delegadas a cada implementador e provedores de estrutura apenas fornecem métodos uniformes para criar e retornar objetos. Tais métodos são inevitáveis ​​para o desenvolvedor da estrutura prosseguir com seu código e tem um nome especial chamado método Factory ( Factory Method Pattern para o padrão subjacente ).

Algumas notas:

  • Se você estiver familiarizado com o 'método de modelo', verá que os métodos de fábrica são frequentemente invocados a partir de métodos de modelo no caso de programas pertencentes a qualquer forma de estrutura. Por outro lado, os métodos de gabarito dos programas aplicativos geralmente são implementações simples de algoritmos específicos e nulos de métodos de fábrica.
  • Além disso, para a plenitude dos pensamentos, usando a estrutura ( mencionada acima ), quando um construtor de ferramentas está construindo uma ferramenta, dentro de cada método de fábrica, em vez de criar um objeto concreto, ele / ela pode delegar ainda mais a responsabilidade em um resumo objeto de fabricação, desde que o fabricante da ferramenta preveja variações dos objetos de concreto para futuras extensões.

Código de amostra:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}
KGhatak
fonte
3
  1. Minha primeira pergunta é sobre a fábrica abstrata. Seu papel é permitir que você crie famílias de objetos concretos (que podem depender de qual fábrica específica você usa), em vez de apenas um único objeto concreto?

Sim. A intenção da Abstract Factory é:

Forneça uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.


  1. A fábrica abstrata retorna apenas um objeto muito grande ou muitos objetos, dependendo de quais métodos você chama?

Idealmente, ele deve retornar um objeto por cada método que o cliente está chamando.

  1. Meu entendimento é que o padrão do método de fábrica possui uma interface Creator que fará com que o ConcreteCreator se encarregue de saber qual produto concreto instanciar. É isso o que significa usar herança para manipular instanciação de objeto?

Sim. O método de fábrica usa herança.

  1. Resumo O padrão de fábrica delega a responsabilidade da instanciação do objeto para outro objeto via composição? O que isto significa?

AbstractFactory define um FactoryMethod e ConcreteFactory é responsável pela construção de um ConcreteProduct. Basta seguir o exemplo de código deste artigo .

Você pode encontrar mais detalhes nas postagens relacionadas do SE:

Qual é a diferença básica entre os padrões de fábrica e abstrato de fábrica?

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

Ravindra babu
fonte
3

O método Factory depende da herança: a criação de objetos é delegada às subclasses, que implementam o método factory para criar objetos.

Resumo O Factory depende da composição do objeto: a criação do objeto é implementada nos métodos expostos na interface do factory.

Diagrama de alto nível de fábrica e padrão de fábrica abstrata,

diagrama

Para mais informações sobre o método Factory, consulte este artigo .

Para obter mais informações sobre o método abstrato de fábrica, consulte este artigo .

user2266614
fonte
2

Para torná-lo muito simples, com interface mínima, focalize "// 1":

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

Aqui pontos importantes: 1. Os mecanismos Factory & AbstractFactory devem usar herança (System.Object-> byte, float ...); portanto, se você tiver herança no programa, o Factory (Abstract Factory provavelmente não estaria lá) provavelmente já existe por design 2. O Creator (MyFactory) conhece o tipo concreto, então retorna o objeto do tipo concreto ao responsável pela chamada (Principal); Em resumo, o tipo de retorno de fábrica seria uma interface.

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

Pontos importantes: 1. Requisito: a Honda criaria "Regular", "Sports", mas o Hero criaria "DarkHorse", "Sports" e "Scooty". 2. por que duas interfaces? Um para o tipo de fabricante (IVehicleFactory) e outro para a fábrica do produto (IVehicle); outra maneira de entender duas interfaces é que a fábrica abstrata tem tudo a ver com a criação de objetos relacionados. então eu recebo a variável pai (IVehicle); então, crio o tipo concreto real chamando CreateSingleVehicle e, em seguida, convertendo o objeto pai para o objeto filho real. O que aconteceria se eu fizesse RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; você obterá ApplicationException e é por isso que precisamos de uma fábrica abstrata genérica que eu explicaria se necessário.

Saurabh
fonte
1

Fábrica abstrata : Uma fábrica de fábricas; uma fábrica que agrupa as fábricas individuais, mas relacionadas / dependentes, sem especificar suas classes concretas. Exemplo abstrato de fábrica

Fábrica : fornece uma maneira de delegar a lógica da instanciação para classes filho. Exemplo de padrão de fábrica

Atul Jain
fonte
0

Eu preferiria o Abstract Factory sobre o Factory Method a qualquer momento. A partir do exemplo de Tom Dalling (ótima explicação), podemos ver que o Abstract Factory é mais compostável, pois tudo o que precisamos fazer é passar um Factory diferente para o construtor (injeção de dependência do construtor em uso aqui). Mas o Factory Method exige que introduzamos uma nova classe (mais coisas para gerenciar) e use subclassificação. Sempre prefira composição ao invés de herança.

he9lin
fonte
0

permita-me colocá-lo com precisão. a maioria das respostas já foi explicada, fornecendo diagramas e exemplos também. então minha resposta seria apenas um forro. minhas próprias palavras: - “o padrão abstrato de fábrica adiciona a camada abstrata em várias implementações de métodos de fábrica. significa que a fábrica abstrata contém ou compõe um ou mais de um padrão de método de fábrica "

Rei
fonte
Isso não está correto. Esse é o equívoco muito comum de que a Abstract Factory não passa de uma fábrica de fábricas.
jaco0646
0

Muitas das respostas acima não fornecem comparações de código entre o padrão Abstract Factory e o Factory Method. A seguir, minha tentativa de explicá-lo via Java. Espero que ajude alguém que precise de uma explicação simples.

Como o GoF diz apropriadamente: O Abstract Factory fornece uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

        public class Client {
            public static void main(String[] args) {
               ZooFactory zooFactory = new HerbivoreZooFactory();       
               Animal animal1 = zooFactory.animal1();
               Animal animal2 = zooFactory.animal2();
               animal1.sound();
               animal2.sound();

               System.out.println();

               AnimalFactory animalFactory = new CowAnimalFactory();
               Animal animal = animalFactory.createAnimal();
               animal.sound();
            }
        }

        public interface Animal {
            public void sound();
        }

        public class Cow implements Animal {

            @Override
            public void sound() {
                System.out.println("Cow moos");
            }

        }

        public class Deer implements Animal {

            @Override
            public void sound() {
                System.out.println("Deer grunts");
            }

        }

        public class Hyena implements Animal {

            @Override
            public void sound() {
                System.out.println("Hyena.java");
            }

        }

        public class Lion implements Animal {

            @Override
            public void sound() {
                System.out.println("Lion roars");
            }

        }

        public interface ZooFactory {
            Animal animal1();

            Animal animal2();
        }

        public class CarnivoreZooFactory implements ZooFactory {

            @Override
            public Animal animal1() {
                return new Lion();
            }

            @Override
            public Animal animal2() {
                return new Hyena();
            }

        }

        public class HerbivoreZooFactory implements ZooFactory{

            @Override
            public Animal animal1() {
                return new Cow();
            }

            @Override
            public Animal animal2() {
                return new Deer();
            }

        }

        public interface AnimalFactory {
            public Animal createAnimal();
        }

        public class CowAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Cow();
            }

        }

        public class DeerAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Deer();
            }

        }

        public class HyenaAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Hyena();
            }

        }

        public class LionAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Lion();
            }

        }
Jatin Shashoo
fonte
Isso não está correto. Esse código implementa o equívoco muito comum de que a Abstract Factory não passa de uma fábrica de fábricas.
precisa saber é o seguinte
1
@ jaco0646 Acredito que no padrão de método de fábrica, o foco está em obter apenas um produto concreto do FactoryImpl. Enquanto no padrão abstrato de fábrica, os FactoryImpls são responsáveis ​​por fornecer vários ConcreteProducts similares / relacionados, para os quais a interface Factory fornece um contrato. Portanto, o ZooFactory não é de todo uma fábrica de fábricas, como você diz, mas apenas uma interface cujos Impls fornecem Produtos de Concreto relacionados entre si. Sinta-se livre para corrigir minha compreensão se você não concordar.
Jatin Shashoo
No Método de Fábrica, o foco está na herança via subclassificação, porque o Método de Fábrica é uma especialização do padrão do Método de Modelo. A resposta mais votada acima mostra um exemplo de código decente.
jaco0646
@ jaco0646 1. Isso significa que no exemplo acima, em vez de usar interfaces para AnimalFactory e fornecer suas implementações, eu deveria ter usado uma classe e substituído o método createAnimal () em suas subclasses: CowAnimalFactory, LionAnimalFactory, etc? 2. Além disso, quais são seus pensamentos sobre o exemplo mostrado para o ZooFactory?
Jatin Shashoo
Para a primeira pergunta: sim. Na segunda, adicionei minha própria resposta a esse tópico em vez de continuar a criticar cada resposta individual.
jaco0646