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

Estaba leyendo patrones de diseño de un sitio web

Allí leo sobre Fábrica, Método de Fábrica y Fábrica Abstracta pero son muy confusos, no tengo claro la definición. De acuerdo a las definiciones

Fábrica: crea objetos sin exponer la lógica de creación de instancias al cliente y hace referencia al objeto recién creado a través de una interfaz común. Es una versión simplificada del método Factory

Método de fábrica: define una interfaz para crear objetos, pero deja que las subclases decidan qué clase instanciar y hace referencia al objeto recién creado a través de una interfaz común.

Abstract Factory: ofrece la interfaz para crear una familia de objetos relacionados, sin especificar explícitamente sus clases.

También miré los otros hilos de stackoverflow con respecto a Abstract Factory vs Factory Method, pero los diagtwigs UML dibujados allí empeoran mi comprensión.

¿Puede alguien decirme por favor

  1. ¿Cómo son estos tres patrones diferentes el uno del otro?
  2. ¿Cuándo usar qué?
  3. Y también si es posible, ¿algún ejemplo de Java relacionado con estos patrones?

Los tres tipos de fábrica hacen lo mismo: son un “constructor inteligente”.

Digamos que quieres poder crear dos tipos de frutas: manzana y naranja.

Fábrica

La fábrica es “fija”, ya que solo tiene una implementación sin subclases. En este caso, tendrás una clase 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 un Apple o un Orange es demasiado complejo de manejar en el constructor para cualquiera.

Método de fábrica

El método de fábrica generalmente se usa cuando tiene un procesamiento genérico en una clase, pero desea variar qué tipo de fruta usa en realidad. Asi que:

 abstract class FruitPicker { protected abstract Fruit makeFruit(); public void pickFruit() { private final Fruit f = makeFruit(); // The fruit we will work on..  } } 

… luego puede reutilizar la funcionalidad común en FruitPicker.pickFruit() implementando un método de fábrica en subclases:

 class OrangePicker extends FruitPicker { @Override protected Fruit makeFruit() { return new Orange(); } } 

Fábrica abstracta

Abstract factory se usa normalmente para cosas como inyección / estrategia de dependencia, cuando se quiere poder crear toda una familia de objetos que deben ser “del mismo tipo”, y tienen algunas clases base comunes. Aquí hay un ejemplo vagamente relacionado con la fruta. El caso de uso aquí es que queremos asegurarnos de que no usemos accidentalmente un OrangePicker en un Apple. Mientras obtengamos nuestra Fruta y Selector de la misma fábrica, coincidirán.

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

Fábrica – Clase de fábrica separada para crear objetos complejos.

Ej: clase FruitFactory para crear objeto de Fruit

 class FruitFactory{ public static Fruit getFruit(){...} } 

Método de fábrica : en lugar de una clase completa separada para fábrica, simplemente agregue un método en esa clase como fábrica.

Ex:

 Calendar.getInstance() (Java's Calendar) 

Método de fábrica abstracto – Fábrica de fábrica

Ejemplo: Supongamos que queremos construir una fábrica para piezas de computadora. Entonces hay varios tipos de computadoras como computadora portátil, computadora de escritorio, servidor.

Entonces para cada tipo de compter necesitamos fábrica. Así que creamos una fábrica de alto nivel de fábricas como la siguiente

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

Ahora estos 3 en sí son fábricas de nuevo. (Va a lidiar con PartFactory en sí, pero bajo el capó, habrá una implementación separada basada en lo que proporcionó en la fábrica abstracta)

  Interface-> PartFactory. getComputerPart(String s), Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory. Usage: new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”) 

EDITAR: editado para proporcionar interfaces exactas para Abstract Factory según las objeciones en los comentarios.

  1. ¿Cómo son estos tres patrones diferentes el uno del otro?

Fábrica: crea objetos sin exponer la lógica de creación de instancias al cliente.

Método de fábrica: defina una interfaz para crear un objeto, pero deje que las subclases decidan qué clase instanciar. El método Factory permite que una clase difiera la instanciación a subclases

Abstract Factory: proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.

El patrón AbstractFactory utiliza la composición para delegar la responsabilidad de crear el objeto a otra clase, mientras que el patrón de diseño del método Factory utiliza la herencia y se basa en la clase o subclase derivada para crear el objeto

  1. ¿Cuándo usar qué?

Fábrica: el cliente solo necesita una clase y no le importa qué implementación concreta está obteniendo.

Método de fábrica: el cliente no sabe qué clases concretas se le requerirá crear en tiempo de ejecución, pero solo quiere obtener una clase que haga el trabajo.

AbstactFactory: 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.

Las clases abstractas de Factory a menudo se implementan con Factory Method. Los métodos de fábrica se suelen llamar dentro de los métodos de plantilla.

  1. Y también si es posible, ¿algún ejemplo de Java relacionado con estos patrones?

Fábrica y FactoryMethod

Intención:

Defina una interfaz para crear un objeto, pero permita que las subclases decidan qué clase instanciar. El método de fábrica permite que una clase difiera la creación de instancias a las subclases.

Diagtwig UML :

enter image description here

Producto: Define una interfaz de los objetos que crea el método Factory.

ConcreteProduct: implementa la interfaz del producto

Creador: declara el método de Fábrica

ConcreateCreator: implementa el método Factory para devolver una instancia de ConcreteProduct

Declaración del problema: cree una fábrica de juegos utilizando Factory Methods, que define la interfaz del juego.

Fragmento de código:

Patrón de fábrica. Cuándo usar los métodos de fábrica?

Comparación con otros patrones de creación:

  1. El diseño comienza utilizando el método Factory (menos complicado, más personalizable, las subclases proliferan) y evoluciona hacia Abstract Factory, Prototype o Builder (más flexible, más complejo) a medida que el diseñador descubre dónde se necesita más flexibilidad

  2. Las clases abstractas de Factory a menudo se implementan con Factory Methods , pero también se pueden implementar utilizando Prototype

Referencias para lecturas adicionales: patrones de diseño de creación de fonts

Cada patrón de diseño prospera para ayudar a garantizar que no se toque el código de trabajo escrito. Todos sabemos que una vez que tocamos el código de trabajo, hay defectos en los flujos de trabajo existentes, y se deben realizar muchas más pruebas para garantizar que no se rompa nada.

Un patrón de fábrica crea objetos en función de los criterios de entrada, lo que garantiza que no es necesario escribir código como si esto creara este tipo de objeto, sino este pequeño objeto. Un buen ejemplo de esto es un sitio web de viajes. Un sitio web de viajes solo puede proporcionar viajes (vuelo, tren, autobús) y / o proporcionar hoteles y / o proporcionar paquetes de atracción turística. Ahora, cuando un usuario selecciona a continuación, el sitio web debe decidir qué objetos necesita crear. En caso de que solo cree el objeto de viaje u hotel también.

Ahora, si prevé agregar otro sitio web a su cartera, y cree que se puede utilizar el mismo núcleo, por ejemplo, un sitio web de uso compartido del automóvil, que ahora busca cabinas y realiza pagos en línea, puede utilizar una fábrica abstracta en su núcleo. De esta forma, puede agregar una fábrica más de taxis y viajes en automóvil.

Ambas fábricas no tienen nada que ver entre sí, por lo que es un buen diseño para mantenerlas en diferentes fábricas.

Espero que esto esté claro ahora. Estudie el sitio web de nuevo manteniendo este ejemplo en mente, con suerte lo ayudará. Y realmente espero haber representado los patrones correctamente :).

 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 el método de fábrica, el usuario puede crear A1 o A2 de AbstractProductA.

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

Pero Abstract Factory tiene más de 1 método de fábrica (por ejemplo, 2 métodos de fábrica), utilizando esos métodos de fábrica creará el conjunto de objetos / objetos relacionados. Utilizando Abstract Factory, el usuario puede crear objetos A1, B1 de AbstractProductA, AbstractProductB