design patterns - qué - Patrones de diseño: Resumen de Fábrica vs Método de Fábrica
patrones de diseño fabrica de objetos (10)
¡Los dos patrones están ciertamente relacionados!
La diferencia entre patrones generalmente es intencional.
El objetivo del Método de Fábrica es "Definir una interfaz para crear un objeto, pero deje que las subclases decidan a qué clase instanciar. El Método de Fábrica permite que una clase retrase la creación de instancias en subclases".
El objetivo de Abstract Factory es "Proporcionar una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas".
Basado puramente en estas declaraciones de intenciones (citadas en GoF), diría que, de hecho, Factory Method es en cierto sentido una Abstract Factory "degenerada" con una familia de una.
En general, tienden a diferir en la implementación, ya que Factory Method es mucho más simple que Abstract Factory .
Sin embargo, están relacionados también en la implementación. Como se menciona en el libro de GoF,
AbstractFactory solo declara una interfaz para crear productos. Depende de las subclases de ConcreteProduct crearlas realmente. La forma más común de hacerlo es definir un método de fábrica para cada producto.
Esta wiki c2 también tiene una discusión interesante sobre este tema.
Nota: las preguntas se encuentran al final de la publicación.
He leído los otros hilos de stackoverflow con respecto a Abstract Factory vs Factory Method . Entiendo la intención de cada patrón. Sin embargo, no tengo claro la definición.
El Método de Fábrica define una interfaz para crear un objeto, pero permite que las subclases decidan a cuál crear una instancia. Un método de fábrica permite que las clases difieran la instanciación a subclases.
Por el contrario, Abstract Factory proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.
The Abstract Factory se ve muy similar al Método de Fábrica . Dibujé algunas clases de UML para ilustrar mi punto.
Nota:
- El diagrama es de www.yuml.com por lo que no están perfectamente orientados. Pero es un servicio gratuito :).
- Los diagramas pueden no ser perfectos. Todavía estoy aprendiendo los patrones de diseño GoF .
Método de fábrica:
Abstract Factory (solo 1 miembro):
Abstract Factory (más miembros):
Preguntas:
- Si Abstract Factory solo tiene un creador y un producto, ¿sigue siendo el patrón Abstract Factory ? (una interfaz para crear familias)
- ¿Se puede crear el creador concreto del método de fábrica desde una interfaz o tiene que ser de una clase? (las clases difieren las instancias de las subclases)
- Si Abstract Factory solo puede tener un creador y un producto, ¿la única diferencia entre Abstract Factory y Factory Method es que el creador de la primera es una interfaz y el creador de la última es una clase?
Aunque han pasado muchos años desde que la gente de cuestionó este tema de manera similar en otras publicaciones (la más antigua es 2009), aún no pude encontrar la respuesta que quería.
- Diferencias entre Abstract Factory Pattern y Factory Method
- ¿Cuál es la diferencia básica entre Factory Factory y Abstract Factory Patterns?
Así que hice algunas horas de investigación en la web, revisé los ejemplos y llegué a esta conclusión, las principales diferencias de Abstract Factory de Factory Method son
- La intención: coherencia o "look-and-feel" : la intención de Abstract Factory es agrupar una familia de objetos con el mismo estilo (por ejemplo, los mismos widgets UI de aspecto y sensación, piezas del mismo estilo, objetos de un mismo SO, etc.) Muchos ejemplos de Abstract Factory mencionan la frase clave "el mismo aspecto y sentimiento".
- Objetos que forman un objeto grupal más grande : Abstract Factory crea una familia de objetos que forman un objeto grupal más grande, no un solo objeto.
- Más tarde, agregue un nuevo estilo : si seguimos usando Factory Method e intentamos agregar un nuevo conjunto de estilos a la infraestructura existente, sería doloroso. Con Abstract Factory, todo lo que tenemos que hacer es simplemente crear una nueva fábrica de concreto que implemente la clase de fábrica abstracta.
Los ejemplos de contador serían
- Una pieza de automóvil para autos deportivos utilizada en un sedán. Esta inconsistencia puede conducir a accidentes.
- Un botón de estilo de Windows en diferentes widgets de GUI del sistema operativo. No va a romper nada sino dañar la experiencia del usuario para algunas personas, como yo.
- Más tarde, descubrimos que nuestro software necesita ejecutarse en la próxima actualización del sistema operativo que necesita un conjunto diferente de objetos del sistema compatibles, manteniendo al mismo tiempo el software compatible con versiones anteriores.
Por lo tanto, cuando un grupo de objetos final debe tener el mismo estilo sin una excepción de un objeto y desea ocultar este detalle de "mantener el mismo estilo", entonces deberíamos usar Abstract Factory.
El patrón de método de fábrica es un patrón de diseño creacional que trata sobre la creación de objetos sin mostrar la clase exacta de objeto que se está creando. Este patrón de diseño básicamente permite que una clase posponga la creación de instancias a subclases.
El patrón Abstract Factory sirve para encapsular a un grupo de fábricas individuales sin exponer las clases concretas. En este modelo, se utiliza una interfaz genérica de una clase abstracta de fábrica para crear el objeto concreto requerido que separa los detalles de la implementación de objetos de su uso y composición. Este patrón de diseño se usa ampliamente en aplicaciones de GUI donde se necesita crear un tipo similar de componentes GUI.
mientras buscaba en google, apareció el siguiente blog que explicaba ambos patrones de diseño brillantemente. eche un vistazo a estos
En mi opinión, la pequeña diferencia entre los dos patrones reside en la aplicabilidad , y así, como ya se dijo, en el Intento .
Recapitulemos las definiciones (ambas de Wikipedia).
Fábrica abstracta
Proporcione una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.
Método de fábrica
Defina una interfaz para crear un objeto , pero deje que las clases que implementan la interfaz decidan qué clase instanciar . El método Factory permite que una clase difiera la instanciación a subclases.
Ambos patrones permiten desacoplar los objetos de usuario de la creación de instancias necesarias (desacoplamiento en tiempo de ejecución), y este es el aspecto común. Ambos patrones permiten crear una jerarquía de fábricas de acuerdo con cualquier necesidad específica, y este es otro aspecto común.
Abstract Factory permite crear varios tipos diferentes de instancias en una subclase y particularizar el comportamiento de las creaciones en sus diferentes subclases; normalmente, el método Factory declara la creación de un solo tipo de objeto que puede particularizarse según el mecanismo de subclasificación. Esa es la diferencia.
Al resumir. Digamos que Product define la superclase de los objetos de creación, y que ProductA y ProductB son dos subclases diferentes. Por lo tanto, el método Abstract Factory tendrá dos métodos, createProductA () y createProductB () que se particularizará (en términos de pasos de creación) en sus subclases específicas: las subclases de fábrica particularizan los pasos de creación para las dos clases definidas de objetos bajo creación
De acuerdo con el ejemplo anterior, el Método de fábrica se implementará de manera diferente, abstrayendo la creación de ProductA y ProductB en tantas fábricas (un método por fábrica), y la especialización adicional de los pasos de creación se delegará en la jerarquía a medida que se construye .
Espero que esto ayude. Describe los diversos tipos de fábricas. Usé Head First Design Patterns como mi referencia. Utilicé yuml.me al diagrama.
Fábrica estática
Es una clase con un Método Estático para producir varios sub tipos de Producto.
Fábrica simple
Es una clase que puede producir varios subtipos de Producto. (Es mejor que la Static Factory. Cuando se agregan nuevos tipos, la clase de producto base no necesita cambiarse solo en la clase Simple Factory)
Método de fábrica
Contiene un método para producir un tipo de producto relacionado con su tipo. (Es mejor que una fábrica simple porque el tipo se difiere a una subclase).
Fábrica abstracta
Produce una familia de tipos que están relacionados. Es notablemente diferente de un método de fábrica, ya que tiene más de un método de tipos que produce. (Esto es complicado, consulte el siguiente diagrama para un mejor ejemplo de la vida real).
Ejemplo del .NET Framework
DbFactoriesProvider es una fábrica simple ya que no tiene subtipos. DbFactoryProvider es una fábrica abstracta ya que puede crear varios objetos de base de datos relacionados, como objetos de conexión y comando.
1.
Parece que la lista de OP (excelentes) del OP ha sido ignorada. Las respuestas actuales simplemente ofrecen definiciones repetidas. Por lo tanto, intentaré abordar las preguntas originales de manera concisa.
- Si Abstract Factory solo tiene un creador y un producto, ¿sigue siendo el patrón Abstract Factory ? (una interfaz para crear familias)
No Una fábrica abstracta debe crear más de un producto para formar una "familia de productos relacionados". El ejemplo de GoF canónico crea ScrollBar()
y Window()
. La ventaja (y el objetivo) es que Abstract Factory puede aplicar un tema común en sus múltiples productos.
- ¿Se puede crear el creador concreto del método de fábrica desde una interfaz o tiene que ser de una clase? (las clases difieren las instancias de las subclases)
Primero, debemos notar que ni Java ni C # existían cuando el GoF escribió su libro. El uso de GoF del término interfaz no está relacionado con los tipos de interfaz introducidos por determinados idiomas. Por lo tanto, el creador concreto se puede crear a partir de cualquier API. El punto importante en el patrón es que la API consume su propio método de fábrica, por lo que una interfaz con un solo método no puede ser un método de fábrica más de lo que puede ser una fábrica abstracta.
- Si Abstract Factory solo puede tener un creador y un producto, ¿la única diferencia entre Abstract Factory y Factory Method es que el creador de la primera es una interfaz y el creador de la última es una clase?
Esta pregunta ya no es válida, siguiendo las respuestas anteriores; sin embargo, si se le deja pensando que la única diferencia entre Abstract Factory y Factory Method es la cantidad de productos creados, considere cómo un cliente consume cada uno de estos patrones. Una fábrica abstracta generalmente se inyecta en su cliente y se invoca mediante composición / delegación. Un método de fábrica debe ser heredado. Entonces, todo vuelve al viejo debate composición vs herencia.
¡Pero estas respuestas han planteado una cuarta pregunta!
- Como, una interfaz con un solo método no puede ser un Método de fábrica más de lo que puede ser una Fábrica abstracta , ¿a qué llamamos una interfaz creacional con un solo método?
Si el método es estático, comúnmente se lo denomina fábrica estática . Si el método no es estático, comúnmente se lo denomina Fábrica simple . Ninguno de estos es un patrón GoF, pero en la práctica son mucho más utilizados.
Por lo que entiendo el significado de las definiciones abstractas de fábricas y métodos de fábrica, la primera se implementa en contexto estático y proporciona objetos en función de los parámetros de entrada.
El segundo usa un objeto ya creado (la familia) que implementa la interfaz del método de fábrica. El método de fábrica luego crea una instancia específica relacionada con el objeto original, sin importar cuál sea.
Por lo tanto, esto generalmente lleva a utilizar ambos patrones juntos, donde en el primer paso crea un objeto general que describe la familia de objetos relacionados. Se llama mediante el método estático getInstance ("mi nombre de familia"). La implementación de dicho método getInstance decide qué objeto familiar se creará.
Luego invoco el método createProduct () en el objeto familiar recién creado y, dependiendo del objeto familiar, se devolverá el nuevo producto.
Parece que estos patrones cooperan con cada uno.
En otras palabras, Abstract Factory se centra en "QUÉ" se creará y en el método de fábrica "CÓMO" se creará.
Si crease una clase de fábrica abstraída (referenciada a través de una interfaz o clase base abstracta) que crea objetos que tiene solo un método para crear objetos, entonces sería un método de fábrica .
Si la fábrica abstraída tiene más de 1 método para crear objetos, entonces sería una fábrica abstracta .
Digamos que hago un administrador que manejará las necesidades de los métodos de acción para un controlador MVC. Si tuviera un método, por ejemplo para crear los objetos del motor que se usarán para crear modelos de vista, entonces sería un patrón de método de fábrica. Por otro lado, si tuviera dos métodos: uno para crear motores de modelos de vista y otro para crear motores de modelos de acción (o lo que sea que quiera llamar al modelo que el método de acción contenga consumidores), entonces sería una fábrica abstracta.
public ActionResult DoSomething(SpecificActionModel model)
{
var actionModelEngine = manager.GetActionModelEngine<SpecificActionModel>();
actionModelEngine.Execute(SpecificActionModelEnum.Value);
var viewModelEngine = manager.GetViewModelEngine<SpecificViewModel>();
return View(viewModelEngine.GetViewModel(SpecificViewModelEnum.Value);
}
Todo lo que debes recordar es que una fábrica abstracta es una fábrica que puede devolver varias fábricas . Entonces, si tienes un AnimalSpeciesFactory puede devolver fábricas como esta:
Mamalfactory, BirdFactory, Fishfactory, ReptileFactory. Ahora que tiene una sola fábrica de AnimalSpeciesFactory, usan el patrón de fábrica para crear objets específicos. Por ejemplo, imagina que obtuviste una Fábrica de reptiles de esta Fábrica de animales, entonces podrías ofrecer crear objetos de reptiles como: serpientes, tortugas, objetos de lagartija.
/*
//Factory methods:
//1. Factory Method - Abstract Creator Class
#include <iostream>
#include <string.h>
using namespace std;
const std::string nineNintyCC = std::string("990CC");
const std::string thousandTwoHundredCC = std::string("1200CC");
const std::string ThousandFiveHundredCC = std::string("1500CC");
const std::string fiveThousandCC = std::string("5000CC");
// Product
class Engine
{
public:
virtual void packEngine() = 0;
};
// Concrete products
// concrete product class one
class C990CCEngine: public Engine
{
public:
void packEngine()
{
cout << "Pack 990CC engine" << endl;
}
};
// concrete class Two
class C1200CCEngine: public Engine
{ public:
void packEngine()
{
cout << "pack 1200CC engine" << endl;
}
};
// Concrete class Three
class C1500CCEngine: public Engine
{
public:
void packEngine()
{
cout << "Pack 1500CC engine" << endl;
}
};
// Car Factory:
class CarFactory{
public:
virtual Engine* createEngine(const std::string& type) = 0;
};
class Factory: public CarFactory
{
public:
Engine *createEngine(const std::string& type)
{
if(0 == nineNintyCC.compare(type))
{
return new C990CCEngine;
}
else if(0 == thousandTwoHundredCC.compare(type))
{
return new C1200CCEngine;
}
else if(0 == ThousandFiveHundredCC.compare(type))
{
return new C1500CCEngine;
}
else
{
cout << "Invalid factory input" << endl;
return NULL;
}
return NULL;
}
};
int main()
{
CarFactory* ptr = new Factory;
Engine*pEngine = ptr->createEngine(nineNintyCC);
if(pEngine)
{
pEngine->packEngine();
delete pEngine;
}
else
{
cout << "No engine exists of your type in our factory" << endl;
}
pEngine = ptr->createEngine(ThousandFiveHundredCC);
if(pEngine)
{
pEngine->packEngine();
delete pEngine;
}
else
{
cout << "No engine exists of your type in our factory" << endl;
}
pEngine = ptr->createEngine(thousandTwoHundredCC);
if(pEngine)
{
pEngine->packEngine();
delete pEngine;
}
else
{
cout << "No engine exists of your type in our factory" << endl;
}
pEngine = ptr-> createEngine(fiveThousandCC);
if(pEngine)
{
pEngine->packEngine();
delete pEngine;
}
else
{
cout << "No engine exists of your type in our factory" << endl;
}
return 0;
}
*/
/*
//
// interface product
#include <iostream>
#include <string>
using namespace std;
class Engine
{
public:
virtual void EngineType() = 0;
};
// concrte product
class AltoEngine: public Engine
{
public:
void EngineType()
{
cout << "Alto Engine" << endl;
}
};
//Concrte product
class SwiftEngine : public Engine
{
public:
void EngineType()
{
cout << "Swift Engine" << endl;
}
};
class Body
{
public:
virtual void bodyType() = 0;
};
class AltoBody: public Body
{
public:
virtual void bodyType()
{
cout << "Alto Car Body" << endl;
}
};
class SwiftBody : public Body
{
public:
void bodyType()
{
cout << "SwiftCar Body" << endl;
}
};
class CarFactory
{
public:
virtual Engine* createEngineProduct() = 0;
virtual Body* createBodyPoduct() = 0;
};
class AltoCarFactory: public CarFactory
{
public:
Engine * createEngineProduct()
{
return new AltoEngine;
}
Body* createBodyPoduct()
{
return new AltoBody;
}
};
class SwiftCarFactory: public CarFactory
{
public:
Engine * createEngineProduct()
{
return new SwiftEngine;
}
Body* createBodyPoduct()
{
return new SwiftBody;
}
};
int main()
{
CarFactory* pAltoFactory = new AltoCarFactory;
Engine* pAltoEngine = pAltoFactory->createEngineProduct();
pAltoEngine->EngineType();
Body* pAltoBody = pAltoFactory->createBodyPoduct();
pAltoBody->bodyType();
CarFactory* pSwiftFactory = NULL;
pSwiftFactory = new SwiftCarFactory;
Engine* pSwiftEngine = pSwiftFactory->createEngineProduct();
pSwiftEngine->EngineType();
Body* pSwfitBody = pSwiftFactory->createBodyPoduct();
pSwfitBody->bodyType();
delete pAltoBody;
delete pAltoFactory;
delete pSwfitBody;
delete pSwiftFactory;
return 0;
}
*/
/*
// One more Factory example;
#include <iostream>
#include <string>
using namespace std;
const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");
// Interface
class CarEngine
{
public:
virtual void engineType() = 0;
};
// Concrete class
class FiatEngine: public CarEngine
{
public:
void engineType()
{
cout << "Fait Engine Engine" << endl;
}
};
// ConcreteClass
class RenaultEngine : public CarEngine
{
public:
void engineType()
{
cout << "Renault Engine" << endl;
}
};
// Concrete class
class MaruthiEngine : public CarEngine
{
public:
void engineType()
{
cout << "Maruthi Engine" << endl;
}
};
// Factory
class CarFactory
{
public:
virtual CarEngine* createFactory(const std::string&) = 0;
};
// EngineFactory
class CarEngineFactory : public CarFactory
{
public:
CarEngine* createFactory(const std::string& type)
{
if(0 == maruthi.compare(type))
{
return new MaruthiEngine;
}
else if(0 == fiat.compare(type))
{
return new FiatEngine;
}
else if(0 == renault.compare(type))
{
return new RenaultEngine;
}
else
{
cout << "Invalid Engine type" << endl;
return NULL;
}
}
};
int main()
{
CarFactory* pCarFactory = new CarEngineFactory;
CarEngine* pMaruthiCarEngine = pCarFactory->createFactory(maruthi);
pMaruthiCarEngine->engineType();
CarEngine* pFiatCarEngine = pCarFactory->createFactory(fiat);
pFiatCarEngine->engineType();
CarEngine* pRenaultCarEngine = pCarFactory->createFactory(renault);
pRenaultCarEngine->engineType();
return 0;
}
*/
/*
// One more Factory example;
#include <iostream>
#include <string>
using namespace std;
const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");
// Interface
class CarEngine
{
public:
virtual void engineType() = 0;
};
// Concrete class
class FiatEngine: public CarEngine
{
public:
void engineType()
{
cout << "Fait Car Engine" << endl;
}
};
// ConcreteClass
class RenaultEngine : public CarEngine
{
public:
void engineType()
{
cout << "Renault Car Engine" << endl;
}
};
// Concrete class
class MaruthiEngine : public CarEngine
{
public:
void engineType()
{
cout << "Maruthi Car Engine" << endl;
}
};
// Interface
class CarBody
{
public:
virtual void bodyType() = 0;
};
// Concrete class
class FiatBody: public CarBody
{
public:
void bodyType()
{
cout << "Fait car Body" << endl;
}
};
// ConcreteClass
class RenaultBody : public CarBody
{
public:
void bodyType()
{
cout << "Renault Body" << endl;
}
};
// Concrete class
class MaruthiBody : public CarBody
{
public:
void bodyType()
{
cout << "Maruthi body" << endl;
}
};
// Factory
class CarFactory
{
public:
virtual CarEngine* createCarEngineProduct() = 0;
virtual CarBody* createCarBodyProduct() = 0;
};
// FiatFactory
class FaitCarFactory : public CarFactory
{
public:
CarEngine* createCarEngineProduct()
{
return new FiatEngine;
}
CarBody* createCarBodyProduct()
{
return new FiatBody;
}
};
// Maruthi Factory
class MaruthiCarFactory : public CarFactory
{
public:
CarEngine* createCarEngineProduct()
{
return new MaruthiEngine;
}
CarBody* createCarBodyProduct()
{
return new MaruthiBody;
}
};
// Renault Factory
class RenaultCarFactory : public CarFactory
{
public:
CarEngine* createCarEngineProduct()
{
return new RenaultEngine;
}
CarBody* createCarBodyProduct()
{
return new RenaultBody;
}
};
int main()
{
// Fiat Factory
CarFactory* pFiatCarFactory = new FaitCarFactory;
CarEngine* pFiatEngine = pFiatCarFactory->createCarEngineProduct();
CarBody* pFiatBody = pFiatCarFactory->createCarBodyProduct();
pFiatEngine->engineType();
pFiatBody->bodyType();
// Renault Car Factory
return 0;
}
*/