java - method - Patrones de diseño: método Factory vs Factory vs Abstract Factory
patron de diseño factory ejemplos (5)
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 diagramas UML dibujados allí empeoran mi comprensión.
¿Puede alguien decirme por favor
- ¿Cómo son estos tres patrones diferentes el uno del otro?
- ¿Cuándo usar qué?
- Y también si es posible, ¿algún ejemplo de Java relacionado con estos patrones?
- ¿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
- ¿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.
- 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.
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:
import java.util.HashMap;
/* Product interface as per UML diagram */
interface Game{
/* createGame is a complex method, which executes a sequence of game steps */
public void createGame();
}
/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
public Chess(){
createGame();
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Chess game");
System.out.println("Opponents:2");
System.out.println("Define 64 blocks");
System.out.println("Place 16 pieces for White opponent");
System.out.println("Place 16 pieces for Black opponent");
System.out.println("Start Chess game");
System.out.println("---------------------------------------");
}
}
class Checkers implements Game{
public Checkers(){
createGame();
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Checkers game");
System.out.println("Opponents:2 or 3 or 4 or 6");
System.out.println("For each opponent, place 10 coins");
System.out.println("Start Checkers game");
System.out.println("---------------------------------------");
}
}
class Ludo implements Game{
public Ludo(){
createGame();
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Ludo game");
System.out.println("Opponents:2 or 3 or 4");
System.out.println("For each opponent, place 4 coins");
System.out.println("Create two dices with numbers from 1-6");
System.out.println("Start Ludo game");
System.out.println("---------------------------------------");
}
}
/* Creator interface as per UML diagram */
interface IGameFactory {
public Game getGame(String gameName);
}
/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {
HashMap<String,Game> games = new HashMap<String,Game>();
/*
Since Game Creation is complex process, we don''t want to create game using new operator every time.
Instead we create Game only once and store it in Factory. When client request a specific game,
Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
*/
public GameFactory(){
games.put(Chess.class.getName(),new Chess());
games.put(Checkers.class.getName(),new Checkers());
games.put(Ludo.class.getName(),new Ludo());
}
public Game getGame(String gameName){
return games.get(gameName);
}
}
public class NonStaticFactoryDemo{
public static void main(String args[]){
if ( args.length < 1){
System.out.println("Usage: java FactoryDemo gameName");
return;
}
GameFactory factory = new GameFactory();
Game game = factory.getGame(args[0]);
System.out.println("Game="+game.getClass().getName());
}
}
salida:
java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
---------------------------------------
Create Checkers game
Opponents:2 or 3 or 4 or 6
For each opponent, place 10 coins
Start Checkers game
---------------------------------------
---------------------------------------
Create Ludo game
Opponents:2 or 3 or 4
For each opponent, place 4 coins
Create two dices with numbers from 1-6
Start Ludo game
---------------------------------------
Game=Chess
Este ejemplo muestra una clase de Factory
implementando FactoryMethod
.
Game
es la interfaz para todo tipo de juegos. Define el método complejo:createGame()
Chess, Ludo, Checkers
son diferentes variantes de juegos, que proporcionan implementación paracreateGame()
public Game getGame(String gameName)
esFactoryMethod
en la claseIGameFactory
GameFactory
pre-crea diferentes tipos de juegos en el constructor. Implementa el método de fábricaIGameFactory
.El nombre del juego se pasa como argumento de línea de comando a
NotStaticFactoryDemo
getGame
enGameFactory
acepta el nombre de un juego y devuelve el correspondiente objeto delGame
.
Comparación con otros patrones de creación:
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
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 fuentes
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 :).
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..
<bla bla bla>
}
}
... 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.
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