Patrón de fábrica abstracta

El patrón de fábrica abstracta (Abstract Factory Pattern) consiste en una súper fábrica que crea otras fábricas. Esta súper fábrica también se conoce como la fábrica de otras fábricas. Este tipo de patrón de diseño pertenece a los patrones de creación y proporciona la mejor manera de crear objetos.

En el patrón de fábrica abstracta, la interfaz es una fábrica responsable de crear objetos relacionados, sin necesidad de especificar explícitamente sus clases. Cada fábrica generada puede proporcionar objetos según el patrón de fábrica.

El patrón de fábrica abstracta proporciona una interfaz para crear una serie de objetos relacionados o interdependientes sin necesidad de especificar clases de implementación concretas. Mediante el uso del patrón de fábrica abstracta, se puede desacoplar al cliente del proceso de creación de productos concretos, de modo que pueda crear una familia de productos a través de la interfaz de fábrica.

Resumen

Intención

Proporcionar una interfaz para crear una serie de objetos relacionados o interdependientes sin especificar sus clases concretas.

Problema principal

El problema de la selección de interfaces.

Escenarios aplicables

Cuando el sistema necesita crear múltiples objetos relacionados o dependientes sin especificar clases concretas.

Solución

Definir múltiples productos dentro de una familia de productos, y que las fábricas concretas implementen los métodos para crear estos productos.

Código clave

Agrupar en una fábrica los métodos de creación de múltiples productos del mismo tipo.

Ejemplo de aplicación

Supongamos que existen diferentes tipos de armarios. Cada armario (fábrica concreta) solo puede guardar un tipo de ropa (productos concretos en conjunto), como ropa de negocios, ropa de moda, etc. Cada conjunto de ropa incluye una prenda superior y pantalones específicos (productos concretos). Todos los armarios son implementaciones concretas de la clase armario (fábrica abstracta), y todas las prendas superiores y pantalones implementan respectivamente la interfaz de prenda superior y la interfaz de pantalones (productos abstractos).

Ventajas

  1. Asegura que los objetos de la misma familia de productos trabajen juntos.
  2. El cliente no necesita conocer la clase concreta de cada objeto, lo que simplifica el código.

Desventajas

Ampliar la familia de productos es muy difícil. Agregar una nueva familia de productos requiere modificar el código de la fábrica abstracta y de todas las fábricas concretas.

Escenarios de uso

  1. Cuando QQ cambia de tema, se reemplaza todo el conjunto de temas a la vez.
  2. Al crear aplicaciones multiplataforma, se generan programas para diferentes sistemas operativos.

Consideraciones

Agregar una nueva familia de productos es relativamente fácil, mientras que agregar una nueva estructura jerárquica de productos es más difícil.

Estructura

El patrón de fábrica abstracta incluye los siguientes roles principales:

  • Fábrica abstracta (Abstract Factory): declara un conjunto de métodos para crear objetos de producto; cada método corresponde a un tipo de producto. La fábrica abstracta puede ser una interfaz o una clase abstracta.
  • Fábrica concreta (Concrete Factory): implementa la interfaz de la fábrica abstracta y se encarga de crear instancias de objetos de producto concretos.
  • Producto abstracto (Abstract Product): define la interfaz común o clase abstracta de un grupo de objetos de producto y describe los métodos públicos de los objetos de producto.
  • Producto concreto (Concrete Product): implementa la interfaz del producto abstracto y define los comportamientos y atributos específicos del producto concreto.

El patrón de fábrica abstracta generalmente involucra una familia de productos relacionados. Cada clase de fábrica concreta se encarga de crear los productos concretos de esa familia. El cliente crea objetos de producto a través de la interfaz de fábrica abstracta, sin necesidad de usar directamente las clases de implementación de los productos concretos.

Implementación

Vamos a crearShapeyColorinterfaces y clases de entidad que implementan estas interfaces. El siguiente paso es crear la clase de fábrica abstractaAbstractFactory. Luego defina las clases de fábricaShapeFactoryyColorFactory, estas dos clases de fábrica extiendenAbstractFactory. Luego cree una clase creadora/generadora de fábricasFactoryProducer。

AbstractFactoryPatternDemoLa clase usaFactoryProducerpara obtenerAbstractFactoryobjetos. PasaráAbstractFactoryinformación de forma aShape(CIRCLE / RECTANGLE / SQUARE), para obtener el tipo de objeto que necesita. Al mismo tiempo, también pasaráAbstractFactoryinformación de color aColor(RED / GREEN / BLUE), para obtener el tipo de objeto que necesita.

抽象工厂模式的 UML 图

Paso 1

Crear una interfaz para la forma.

Shape.java

public interface Shape { void draw(); }

Paso 2

Crear clases de entidad que implementen la interfaz.

Rectangle.java

Rectangle.java

public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }

Square.java

public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }

Circle.java

public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }

Paso 3

Crear una interfaz para el color.

Color.java

public interface Color { void fill(); }

Paso 4

Crear clases de entidad que implementen la interfaz.

Red.java

public class Red implements Color { @Override public void fill() { System.out.println("Inside Red::fill() method."); } }

Green.java

public class Green implements Color { @Override public void fill() { System.out.println("Inside Green::fill() method."); } }

Blue.java

public class Blue implements Color { @Override public void fill() { System.out.println("Inside Blue::fill() method."); } }

Paso 5

Crear una clase abstracta para obtener fábricas de objetos Color y Shape.

AbstractFactory.java

public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape); }

Paso 6

Crear clases de fábrica que extiendan AbstractFactory y generen objetos de las clases de entidad según la información dada.

ShapeFactory.java

public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } }

ColorFactory.java

public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); } else if(color.equalsIgnoreCase("GREEN")){ return new Green(); } else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } }

Paso 7

Crear una clase creadora/generadora de fábricas que obtenga la fábrica pasando información de forma o color.

FactoryProducer.java

public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } }

Paso 8

Usar FactoryProducer para obtener AbstractFactory, pasando información de tipo para obtener los objetos de las clases de entidad.

AbstractFactoryPatternDemo.java

public class AbstractFactoryPatternDemo { public static void main(String[] args) { //Obtener la fábrica de formas AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //Obtener el objeto con forma Circle Shape shape1 = shapeFactory.getShape("CIRCLE"); //Llamar al método draw de Circle shape1.draw(); //Obtener el objeto con forma Rectangle Shape shape2 = shapeFactory.getShape("RECTANGLE"); //Llamar al método draw de Rectangle shape2.draw(); //Obtener el objeto con forma Square Shape shape3 = shapeFactory.getShape("SQUARE"); //Llamar al método draw de Square shape3.draw(); //Obtener la fábrica de colores AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //Obtener el objeto con color Red Color color1 = colorFactory.getColor("RED"); //Llamar al método fill de Red color1.fill(); //Obtener el objeto con color Green Color color2 = colorFactory.getColor("GREEN"); //Llamar al método fill de Green color2.fill(); //Obtener el objeto con color Blue Color color3 = colorFactory.getColor("BLUE"); //Llamar al método fill de Blue color3.fill(); } }

Paso 9

Ejecutar el programa y mostrar el resultado:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
Otras extensiones