Patrón de fábrica abstracto

format_list_bulleted Contenido keyboard_arrow_down
ImprimirCitar
Diagrama de clase UML

El patrón de software de fábrica abstracta proporciona una forma de encapsular un grupo de fábricas individuales que tienen un tema común sin especificar sus clases concretas. En el uso normal, el software del cliente crea una implementación concreta de la fábrica abstracta y luego usa la interfaz genérica de la fábrica para crear los objetos concretos que forman parte del tema. El cliente no sabe qué objetos concretos recibe de cada una de estas fábricas internas, ya que utiliza únicamente las interfaces genéricas de sus productos. Este patrón separa los detalles de implementación de un conjunto de objetos de su uso general y se basa en la composición de objetos, ya que la creación de objetos se implementa en métodos expuestos en la interfaz de fábrica.

Un ejemplo es una clase de fábrica abstracta DocumentCreator que proporciona interfaces para crear una serie de productos (por ejemplo, createLetter() y createResume()). El sistema tendría cualquier número de versiones concretas derivadas de la clase DocumentCreator como FancyDocumentCreator o ModernDocumentCreator, cada una con una implementación diferente de createLetter() y createResume() que crearían objetos correspondientes como FancyLetter o ModernResume. Cada uno de estos productos se deriva de una clase abstracta simple como Letter o Resume que el cliente conoce. El código del cliente adquiriría una instancia apropiada de DocumentCreator y llamaría a sus métodos de fábrica. Cada uno de los objetos resultantes se crearía a partir de la misma implementación de DocumentCreator y compartiría un tema común. El cliente solo necesitaría saber cómo manejar la clase abstracta Letter o Resume, no la versión específica que fue creada por la fábrica concreta.

Una fábrica es la ubicación de una clase concreta en el código en el que se construyen los objetos. La implementación del patrón pretende aislar la creación de objetos de su uso y crear familias de objetos relacionados sin tener que depender de sus clases concretas. Esto permite que se introduzcan nuevos tipos derivados sin cambios en el código que usa la clase base.

El uso de este patrón permite implementaciones concretas intercambiables sin cambiar el código que las usa, incluso en tiempo de ejecución. Sin embargo, el empleo de este patrón, al igual que con patrones de diseño similares, puede generar una complejidad innecesaria y un trabajo adicional en la escritura inicial del código. Además, los niveles más altos de separación y abstracción pueden dar como resultado sistemas que son más difíciles de depurar y mantener.

Resumen

El patrón de diseño de fábrica abstracto es uno de los 23 patrones conocidos descritos en el libro Design Patterns de 1994. Se puede utilizar para resolver problemas como:

  • ¿Cómo puede una aplicación ser independiente de cómo se crean sus objetos?
  • ¿Cómo puede una clase ser independiente de cómo se crean los objetos que requiere?
  • ¿Cómo se pueden crear familias de objetos relacionados o dependientes?

La creación de objetos directamente dentro de la clase que requiere los objetos es inflexible porque hacerlo compromete la clase con objetos particulares y hace que sea imposible cambiar la creación de instancias más adelante independientemente de la clase sin tener que cambiarla. Evita que la clase sea reutilizable si se requieren otros objetos y hace que la clase sea difícil de probar porque los objetos reales no se pueden reemplazar con objetos ficticios.

El patrón describe cómo resolver tales problemas:

  • Encapsular la creación de objetos en un objeto separado (factorial) definiendo e implementando una interfaz para crear objetos.
  • Delegar la creación de objetos a un objeto de fábrica en lugar de crear objetos directamente.

Esto hace que una clase sea independiente de cómo se crean sus objetos. Una clase se puede configurar con un objeto de fábrica, que utiliza para crear objetos, y el objeto de fábrica se puede intercambiar en tiempo de ejecución.

Definición

El libro Patrones de diseño describe el patrón de fábrica abstracto como "una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas."

Uso

La fábrica determina el tipo concreto real de objeto que se creará, y es aquí donde se crea realmente el objeto (en Java, por ejemplo, mediante el operador nuevo). Sin embargo, la fábrica solo devuelve un puntero abstracto al objeto concreto creado.

Esto aísla el código del cliente de la creación de objetos haciendo que los clientes soliciten que un objeto de fábrica cree un objeto del tipo abstracto deseado y devuelva un puntero abstracto al objeto.

Como la fábrica solo devuelve un puntero abstracto, el código de cliente que solicitó el objeto de la fábrica no tiene conocimiento del tipo concreto real del objeto que se creó, y no se ve afectado por él. Sin embargo, el tipo de un objeto concreto (y por lo tanto de una fábrica concreta) es conocido por la fábrica abstracta; por ejemplo, la fábrica puede leerlo desde un archivo de configuración. El cliente no necesita especificar el tipo, ya que el tipo ya se ha especificado en el archivo de configuración. En particular, esto significa:

  • El código cliente no tiene ningún conocimiento del tipo de hormigón, sin necesidad de incluir ningún fichero de cabecera o declaraciones de clase relacionadas con él. El código del cliente se ocupa únicamente del tipo abstracto. Los objetos de un tipo concreto son creados por la fábrica, pero el código del cliente accede a tales objetos sólo a través de sus interfaces abstractas.
  • La adición de nuevos tipos de hormigón se realiza modificando el código del cliente para utilizar una fábrica diferente, una modificación que es típicamente una línea en un archivo. La fábrica diferente entonces crea objetos de un tipo de hormigón diferente pero todavía devuelve un puntero del igual tipo abstracto como antes, aislante el código cliente del cambio. Esto es significativamente más fácil que modificar el código del cliente para instantánear un nuevo tipo, lo que requeriría cambiar cada ubicación en el código donde se crea un nuevo objeto, así como asegurar que todas las ubicaciones de código tengan conocimiento del nuevo tipo de hormigón, por ejemplo, incluyendo un archivo de cabecera de clase concreto. Si todos los objetos de fábrica se almacenan globalmente en un objeto singleton, y todo el código de cliente pasa a través del singleton para acceder a la fábrica adecuada para la creación de objetos, entonces cambiar fábricas es tan fácil como cambiar el objeto singleton.

Estructura

Diagrama UML

In this class diagram example, the method createButton on the GUIFactory interface returns objects of type Button. The exact implementation of Button that is returned depends on which implementation of GUIFactory is handling the method call.
En este ejemplo de diagrama de clase, el método createButton sobre GUIFactory interfaz devuelve objetos de tipo Button. La aplicación exacta de Button que se devuelve depende de qué aplicación GUIFactory está manejando la llamada del método.
A sample UML class and sequence diagram for the abstract factory design pattern. [7]
Un diagrama de clase y secuencia UML muestra para el patrón de diseño de fábrica abstracto.

En el diagrama de clases UML anterior, la clase Client que requiere los objetos ProductA y ProductB no instancia ProductA1 y ProductB1 clases directamente. En su lugar, Client se refiere a la interfaz AbstractFactory para crear objetos, lo que hace que Client sea independiente de cómo se crean los objetos (qué clases concretas son instanciado). La clase Factory1 implementa la interfaz AbstractFactory instanciando las clases ProductA1 y ProductB1.

El diagrama de secuencia UML muestra las interacciones en tiempo de ejecución. El objeto Client llama a createProductA() en el objeto Factory1, que crea y devuelve un objeto ProductA1. A partir de entonces, Client llama a createProductB() en Factory1, que crea y devuelve un objeto ProductB1.

Gráfico LePUS3

legend
leyenda

Ejemplo de Python

desde abc importación ABC, abstractodesde Sys importación plataformaclase Button()ABC): @abstractmethod def pintura()auto): pasoclase LinuxButton()Button): def pintura()auto): retorno "Render un botón en un estilo Linux"clase WindowsButton()Button): def pintura()auto): retorno "Render un botón en un estilo de Windows"clase MacOSButton()Button): def pintura()auto): retorno "Render un botón en un estilo MacOS"clase GUI Factory()ABC): @abstractmethod def create_button()auto): pasoclase LinuxFactory()GUI Factory): def create_button()auto): retorno LinuxButton()clase WindowsFactory()GUI Factory): def create_button()auto): retorno WindowsButton()clase MacOSFactory()GUI Factory): def create_button()auto): retorno MacOSButton()si plataforma == "linux": fábrica = LinuxFactory()Elif plataforma == "darwin": fábrica = MacOSFactory()Elif plataforma == "win32": fábrica = WindowsFactory()más: aumento No Implemented Error()f"No implementado para su plataforma: {}plataforma}")botón = fábrica.create_button()resultado = botón.pintura()impresión()resultado)

Implementación alternativa utilizando las propias clases como fábricas:

desde abc importación ABC, abstractodesde Sys importación plataformaclase Button()ABC): @abstractmethod def pintura()auto): pasoclase LinuxButton()Button): def pintura()auto): retorno "Render un botón en un estilo Linux"clase WindowsButton()Button): def pintura()auto): retorno "Render un botón en un estilo de Windows"clase MacOSButton()Button): def pintura()auto): retorno "Render un botón en un estilo MacOS"si plataforma == "linux": fábrica = LinuxButtonElif plataforma == "darwin": fábrica = MacOSButtonElif plataforma == "win32": fábrica = WindowsButtonmás: aumento No Implemented Error()f"No implementado para su plataforma: {}plataforma}")botón = fábrica()resultado = botón.pintura()impresión()resultado)

Contenido relacionado

Transporte en el Reino Unido

El transporte en el Reino Unido se facilita con redes viales, aéreas, ferroviarias y acuáticas. Una red vial radial totaliza 29,145 millas de carreteras...

Relación de compresión de datos

Relación de compresión de datos, también conocida como potencia de compresión, es una medida de la reducción relativa en el tamaño de la representación...

Transporte en República Dominicana

El transporte en la República Dominicana utiliza un sistema de carreteras, aeropuertos, puertos, muelles y un ferrocarril...
Más resultados...
Tamaño del texto:
undoredo
format_boldformat_italicformat_underlinedstrikethrough_ssuperscriptsubscriptlink
save