Diferencias entre Abstract Factory Pattern y Factory Method

Sé que hay muchas publicaciones sobre las diferencias entre estos dos patrones, pero hay algunas cosas que no puedo encontrar.

Por lo que he estado leyendo, veo que el patrón de método de fábrica le permite definir cómo crear un solo producto concreto pero ocultar la implementación del cliente, ya que verá un producto genérico. Mi primera pregunta es sobre la fábrica abstracta. ¿Su función es permitirle crear familias de objetos concretos (que pueden depender de la fábrica específica que utilice) en lugar de solo un objeto concreto? ¿La fábrica abstracta solo devuelve un objeto muy grande o muchos objetos dependiendo de qué métodos llame?

Mis últimas dos preguntas son sobre una única cita que no puedo entender completamente que he visto en numerosos lugares:

Una diferencia entre los dos es que con el patrón Abstract Factory, una clase delega la responsabilidad de la instanciación de objetos en otro objeto a través de la composición, mientras que el patrón Factory Method utiliza la herencia y depende de una subclase para manejar la creación de objetos deseada.

Tengo entendido que el patrón de método de fábrica tiene una interfaz de Creador que hará que ConcreteCreator se encargue de saber qué ConcreteProduct crear. ¿Esto es lo que significa al usar la herencia para manejar la instanciación de objetos?

Ahora con respecto a esa cita, ¿cómo exactamente el patrón Abstract Factory delega la responsabilidad de la instanciación de objetos a otro objeto a través de la composición? ¿Qué significa esto? Parece que el patrón Abstract Factory también usa la herencia para hacer el proceso de construcción también a mis ojos, pero de nuevo todavía estoy aprendiendo sobre estos patrones.

Cualquier ayuda especialmente con la última pregunta, sería muy apreciada.

    La diferencia entre los dos

    La principal diferencia entre un “método de fábrica” ​​y una “fábrica abstracta” es que el método de fábrica es un método único y una fábrica abstracta es un objeto. Creo que muchas personas confunden estos dos términos y comienzan a usarlos indistintamente. Recuerdo que tuve dificultades para encontrar exactamente cuál era la diferencia cuando los aprendí.

    Debido a que el método de fábrica es solo un método, puede ser anulado en una subclase, de ahí la segunda mitad de su cotización:

    … el patrón del Método de Fábrica usa herencia y depende de una subclase para manejar la instanciación del objeto deseado.

    La cita supone que un objeto llama a su propio método de fábrica aquí. Por lo tanto, lo único que podría cambiar el valor de retorno sería una subclase.

    La fábrica abstracta es un objeto que tiene múltiples métodos de fábrica. Mirando la primera mitad de su presupuesto:

    … con el patrón Abstract Factory, una clase delega la responsabilidad de la instanciación de objetos a otro objeto a través de la composición …

    Lo que están diciendo es que hay un objeto A, que quiere hacer un objeto Foo. En lugar de crear el objeto Foo en sí mismo (por ejemplo, con un método de fábrica), obtendrá un objeto diferente (la fábrica abstracta) para crear el objeto Foo.

    Ejemplos de código

    Para mostrarle la diferencia, este es un método de fábrica en 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(); } } 

    Y aquí hay una fábrica abstracta en 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 

    Abstract factory crea una clase base con métodos abstractos que definen los métodos para los objetos que deberían crearse. Cada clase de fábrica que deriva la clase base puede crear su propia implementación de cada tipo de objeto.

    enter image description here

    El método de fábrica es simplemente un método simple utilizado para crear objetos en una clase. Por lo general, se agrega en la raíz agregada (La clase Order tiene un método llamado CreateOrderLine )

    enter image description here

    Fábrica abstracta

    En el siguiente ejemplo, diseñamos una interfaz para poder desacoplar la creación de colas de un sistema de mensajería y, por lo tanto, podemos crear implementaciones para diferentes sistemas de colas sin tener que cambiar la base de códigos.

     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

    El problema en los servidores HTTP es que siempre necesitamos una respuesta para cada solicitud.

     public interface IHttpRequest { // .. all other methods .. IHttpResponse CreateResponse(int httpStatusCode); } 

    Sin el método de fábrica, los usuarios del servidor HTTP (es decir, los progtwigdores) se verían obligados a utilizar clases específicas de implementación que IHttpRequest el propósito de la interfaz IHttpRequest .

    Por lo tanto, presentamos el método de fábrica para que la creación de la clase de respuesta también se abstraiga.

    Resumen

    La diferencia es que el propósito de la clase que contiene un método de fábrica no es crear objetos , mientras que una fábrica abstracta solo debe usarse para crear objetos.

    Se debe tener cuidado al usar métodos de fábrica, ya que es fácil romper el LSP ( principio de sustitución de Liskovs ) al crear objetos.

    La diferencia entre AbstractFactory y los patrones de diseño de fábrica son los siguientes:

    • El Método de Fábrica se usa para crear un solo producto, pero Abstract Factory trata de crear familias de productos relacionados o dependientes.
    • El patrón Método de fábrica expone un método al cliente para crear el objeto, mientras que en el caso de Abstract Factory exponen una familia de objetos relacionados que pueden constar de estos métodos de Fábrica.
    • El patrón de método de fábrica oculta la construcción de un solo objeto donde, como método abstracto de fábrica, se oculta la construcción de una familia de objetos relacionados. Las fábricas abstractas generalmente se implementan usando (un conjunto de) métodos de fábrica.
    • El patrón AbstractFactory usa la composición para delegar la responsabilidad de crear objetos a otra clase, mientras que el patrón de diseño de Factory usa la herencia y depende de la clase o subclase derivada para crear el objeto.
    • La idea detrás del patrón Método de fábrica es que permite que el cliente no sepa qué clases concretas se le requerirá crear en tiempo de ejecución, pero solo quiere obtener una clase que haga el trabajo, mientras que el patrón AbstractFactory es el mejor. utilizado cuando su sistema tiene que crear múltiples familias de productos o desea proporcionar una biblioteca de productos sin exponer los detalles de implementación.

    Implementación del patrón de método de fábrica: Método de fábrica UML

    Implementación del patrón AbstractFactory:

    Resumen de fábrica UML

    Abstract Factory es una interfaz para crear productos relacionados, pero Factory Method es solo un método. Abstract Factory puede implementarse mediante múltiples métodos de fábrica.

    Resumen de fábrica UML

    Considera este ejemplo para una fácil comprensión.

    ¿Qué ofrecen las compañías de telecomunicaciones? Banda ancha, línea telefónica y móvil, por ejemplo, y se le pide que cree una aplicación para ofrecer sus productos a sus clientes.

    En general, lo que harías aquí es crear los productos, es decir, banda ancha, línea telefónica y móvil a través de tu Método de Fábrica, donde sabes qué propiedades tienes para esos productos y es muy directo.

    Ahora, la compañía quiere ofrecer a sus clientes un conjunto de sus productos, es decir, banda ancha, línea telefónica y teléfono móvil, y aquí viene la fábrica abstracta para jugar.

    Abstract Factory es, en otras palabras, la composición de otras fábricas que son responsables de crear sus propios productos y Abstract Factory sabe cómo colocar estos productos de manera más significativa con respecto a sus propias responsabilidades.

    En este caso, BundleFactory es Abstract Factory, BroadbandFactory , PhonelineFactory y MobileFactory son la Factory . Para simplemente más, estas fábricas tendrán el método de fábrica para inicializar los productos individuales.

    Se el ejemplo de código a continuación:

     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 } } 

    Dejemos en claro que la mayor parte del tiempo en el código de producción, usamos patrones abstractos de fábrica porque la clase A está progtwigda con la interfaz B. Y A necesita crear instancias de B. Entonces, A debe tener un objeto de fábrica para producir instancias de B Así que A no depende de ninguna instancia concreta de B. Espero que ayude.

    Comprenda las diferencias en las motivaciones:

    Supongamos que está construyendo una herramienta donde tiene objetos y una implementación concreta de las interrelaciones de los objetos. Como prevé variaciones en los objetos, ha creado un direccionamiento indirecto asignando la responsabilidad de crear variantes de los objetos a otro objeto ( lo llamamos fábrica abstracta ). Esta abstracción encuentra un gran beneficio ya que prevé extensiones futuras que necesitan variantes de esos objetos.

    Otra motivación bastante intrigante en esta línea de pensamiento es un caso en el que todos o ninguno de los objetos de todo el grupo tendrán una variante correspondiente. En función de algunas condiciones, se utilizará cualquiera de las variantes y, en cada caso, todos los objetos deben ser de la misma variante. Esto puede ser un poco contradictorio de entender, ya que a menudo pensamos que, siempre que las variantes de un objeto sigan un contrato uniforme común ( interfaz en un sentido más amplio ), el código de implementación concreto nunca debería romperse. El hecho intrigante aquí es que, no siempre esto es cierto, especialmente cuando el comportamiento esperado no puede ser modelado por un contrato de progtwigción.

    Un simple ( tomando prestada la idea de GoF ) es cualquier aplicación GUI decir un monitor virtual que emula la apariencia de MS, Mac o el sistema operativo Fedora. Aquí, por ejemplo, cuando todos los objetos del widget como la ventana, el botón, etc. tienen una variante MS, excepto una barra de desplazamiento derivada de la variante MAC, el propósito de la herramienta falla.

    Estos casos anteriores forman la necesidad fundamental de Abstract Factory Pattern .

    Por otro lado, imagine que está escribiendo un marco para que muchas personas puedan construir varias herramientas ( como la que se muestra en los ejemplos anteriores ) utilizando su marco. Por la sola idea de un marco, no es necesario, aunque no podría usar objetos concretos en su lógica. Prefieres poner algunos contratos de alto nivel entre varios objetos y cómo interactúan. Mientras que usted ( como desarrollador de framework ) se mantiene en un nivel muy abstracto, cada creador de la herramienta se ve obligado a seguir sus construcciones de framework. Sin embargo, ellos ( los creadores de herramientas ) tienen la libertad de decidir qué objeto construir y cómo interactuarán todos los objetos que crean. A diferencia del caso anterior ( de Abstract Factory Pattern ), usted ( como creador del marco ) no necesita trabajar con objetos concretos en este caso; y más bien puede permanecer en el nivel de contrato de los objetos. Además, a diferencia de la segunda parte de las motivaciones anteriores, usted o los constructores de herramientas nunca tienen la situación de mezclar objetos de variantes. Aquí, mientras el código de la estructura permanece en el nivel de contrato, cada generador de herramientas está restringido ( por la naturaleza del caso ) a usar sus propios objetos. En este caso, las creaciones de objetos se delegan a cada implementador y los proveedores de marcos solo proporcionan métodos uniformes para crear y devolver objetos. Tales métodos son inevitables para que el desarrollador del framework proceda con su código y tiene un nombre especial llamado Método de fábrica ( Patrón de método de fábrica para el patrón subyacente ).

    Algunas notas:

    • Si está familiarizado con el ‘método de plantilla’, verá que los métodos de fábrica a menudo se invocan desde métodos de plantilla en el caso de progtwigs pertenecientes a cualquier forma de marco. Por el contrario, los métodos de plantilla de los progtwigs de aplicación a menudo son simples implementaciones de algoritmos específicos y carecen de métodos de fábrica.
    • Además, para la completitud de los pensamientos, utilizando el marco ( mencionado anteriormente ), cuando un generador de herramientas está construyendo una herramienta, dentro de cada método de fábrica, en lugar de crear un objeto concreto, él / ella puede delegar aún más la responsabilidad en un resumen -factor de fábrica, siempre que el generador de herramientas prevea variaciones de los objetos concretos para futuras extensiones.

    Código de muestra:

     //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 } …. } 
    1. Mi primera pregunta es sobre la fábrica abstracta. ¿Su función es permitirle crear familias de objetos concretos (que pueden depender de la fábrica específica que utilice) en lugar de solo un objeto concreto?

    Sí. La intención de Abstract Factory es:

    Proporcione una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.


    1. ¿La fábrica abstracta solo devuelve un objeto muy grande o muchos objetos dependiendo de qué métodos llame?

    Idealmente, debería devolver un objeto por el método que el cliente está invocando.

    1. Tengo entendido que el patrón de método de fábrica tiene una interfaz de Creador que hará que ConcreteCreator se encargue de saber qué ConcreteProduct crear. ¿Esto es lo que significa al usar la herencia para manejar la instanciación de objetos?

    Sí. El método de fábrica usa herencia.

    1. El patrón abstracto de fábrica delega la responsabilidad de la instanciación de objetos a otro objeto a través de la composición. ¿Qué significa esto?

    AbstractFactory define FactoryMethod y ConcreteFactory es responsable de la construcción de ConcreteProduct. Simplemente siga el ejemplo del código en este artículo .

    Puede encontrar más detalles en publicaciones relacionadas de SE:

    ¿Cuál es la diferencia básica entre Factory Factory y Abstract Factory Patterns?

    Patrones de diseño: método Factory vs Factory vs Abstract Factory

    La principal diferencia entre Abstract Factory y Factory Method es que Abstract Factory está implementado por Composition ; pero el Método de Fábrica es implementado por Herencia .

    Sí, lo lees correctamente: la principal diferencia entre estos dos patrones es la antigua composición frente al debate sobre la herencia .

    No voy a reproducir los diagtwigs UML aquí, ya que se pueden encontrar en numerosos lugares. Quiero proporcionar ejemplos de código; sin embargo, porque creo que combinar los ejemplos de las dos respuestas principales en este hilo dará una mejor demostración que cualquiera de las dos respuestas. Además, he agregado la terminología utilizada en el libro (GoF) a los nombres de clases y métodos.

    Fábrica abstracta

    1. El punto más importante para entender aquí es que la fábrica abstracta se inyecta en el cliente. Es por eso que decimos que Abstract Factory está implementado por Composition. A menudo, un marco de dependency injection realizaría esa tarea; pero no se requiere un marco para DI.
    2. ¡El segundo punto crítico es que las fábricas de hormigón aquí no son implementaciones de Método de Fábrica! El código de ejemplo para el Método de Fábrica se muestra más abajo.
    3. Y finalmente, el tercer punto a tener en cuenta es la relación entre los productos: en este caso, las colas de salida y respuesta. Una fábrica de concreto produce colas Azure, la otra MSMQ. El GoF se refiere a esta relación de producto como una “familia” y es importante tener en cuenta que la familia en este caso no significa jerarquía de clase.
     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. El punto más importante para comprender aquí es que ConcreteCreator es el cliente. En otras palabras, el cliente es una subclase cuyo padre define factoryMethod() . Es por eso que decimos que el Método de Fábrica es implementado por Herencia.
    2. El segundo punto crítico es recordar que el Patrón de Método de Fábrica no es más que una especialización del Patrón de Método de Plantilla. Los dos patrones comparten una estructura idéntica. Solo difieren en el propósito. El Método de Fábrica es creacional (construye algo) mientras que el Método de Plantilla es conductual (computa algo).
    3. Y finalmente, el tercer punto a tener en cuenta es que la clase del Creator (padre) invoca su propio factoryMethod() . Si eliminamos anOperation() de la clase principal, dejando solo un único método atrás, ya no es el patrón Método de fábrica. En otras palabras, Factory Method no se puede implementar con menos de dos métodos en la clase principal; y uno debe invocar al otro.
     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. Y diversos patrones de fábrica

    Tenga en cuenta que aunque el GoF define dos patrones de fábrica diferentes, estos no son los únicos patrones de fábrica existentes. Ni siquiera son necesariamente los patrones de Fábrica más comúnmente utilizados. Un tercer ejemplo famoso es el Static Factory Pattern de Josh Bloch de Effective Java. El libro de Head First Design Patterns incluye otro patrón que llaman Simple Factory.

    No caiga en la trampa de suponer que cada patrón de fábrica debe coincidir con uno del GoF.

    Para que sea muy simple con la interfaz mínima y enfócate en “// 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; } } 

    Aquí los puntos importantes: 1. Los mecanismos Factory & AbstractFactory deben usar herencia (System.Object-> byte, float …); así que si tiene herencia en el progtwig, entonces Factory (Abstract Factory no estaría allí con toda probabilidad) ya está allí por el diseño 2. Creator (MyFactory) conoce el tipo de concreto, por lo que devuelve el tipo concreto a la persona que llama (Main); En resumen, el tipo de devolución de fábrica sería una interfaz.

     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(); } } 

    Puntos importantes: 1. Requisito: Honda crearía “Regular”, “Deportes”, pero Hero crearía “DarkHorse”, “Sports” y “Scooty”. 2. ¿por qué dos interfaces? Uno para el tipo de fabricante (IVehicleFactory) y otro para la fábrica de productos (IVehicle); Otra forma de entender 2 interfaces es que la fábrica abstracta tiene que ver con la creación de objetos relacionados. 2. La trampa es que los niños de IVehicleFactory regresan y el vehículo (en lugar de concreto en la fábrica); entonces obtengo la variable principal (IVehicle); luego creo un tipo de concreto real llamando CreateSingleVehicle y luego lanzando el objeto principal al objeto hijo real. ¿Qué pasaría si hago RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular"); ; obtendrá la excepción ApplicationException y es por eso que necesitamos una fábrica abstracta genérica que explicaría si fuera necesario. Espero que ayude desde la audiencia principiante hasta la intermedia.

    Ejemplo de vida real. (Fácil de recordar)

    Fábrica

    Imagina que estás construyendo una casa y te acercas a un carpintero por una puerta. Usted da la medida de la puerta y sus requisitos, y él le construirá una puerta. En este caso, el carpintero es una fábrica de puertas. Sus especificaciones son entradas para la fábrica, y la puerta es la salida o producto de fábrica.

    Fábrica abstracta

    Ahora, considere el mismo ejemplo de la puerta. Puede ir a un carpintero, o puede ir a una tienda de puertas de plástico o una tienda de PVC. Todos ellos son fábricas de puertas. Según la situación, usted decide a qué tipo de fábrica necesita acercarse. Esto es como una fábrica abstracta.

    He explicado aquí tanto el patrón de método de Fábrica como el patrón abstracto de fábrica comenzando por no usarlos explicando problemas y luego resolviendo problemas usando los patrones anteriores https://github.com/vikramnagineni/Design-Patterns/tree/master

    Yo preferiría Abstract Factory sobre Factory Method en cualquier momento. Del ejemplo de Tom Dalling (gran explicación por cierto) más arriba, podemos ver que Abstract Factory es más composable en cuanto a que todo lo que tenemos que hacer es pasar una fábrica diferente al constructor (dependency injection de constructor en uso aquí). Pero Factory Method nos exige introducir una nueva clase (más cosas para administrar) y usar subclassing. Siempre prefiero la composición a la herencia.

    permítanme ponerlo con precisión. la mayoría de las respuestas ya han explicado, proporcionó diagtwigs y ejemplos también. entonces mi anwer sería solo un trazador de líneas. Mis propias palabras: “el patrón abstracto de fábrica se agrega en la capa abstracta sobre múltiples implementaciones de métodos de fábrica. significa que la fábrica abstracta contiene o compone uno o más patrones de métodos de fábrica “

    Muchas de las respuestas anteriores no proporcionan comparaciones de código entre Abstract Factory y Factory Method pattern. Lo que sigue es mi bash de explicarlo a través de Java. Espero que ayude a alguien que necesita una explicación simple.

    Como dice correctamente GoF: Abstract Factory proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases 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(); } }