Patrones de diseño para desarrollo de software

Maria Garcia-Ch
Nowports Tech and Product
6 min readJun 17, 2020
Foto por Kelly Sikkema en Unsplash

Para lograr que un equipo de programadores comprendan un código escrito de manera colaborativa, es necesario estandarizarlo mediante un patrón de diseño. Adicionalmente, tiene otros beneficios como la capacidad de reutilizar código y ahorrar tiempo en su construcción y mantenimiento.

Los patrones de diseño son una herramienta muy útil, que proporciona un conjunto de reglas y especificaciones para que los desarrolladores resuelvan problemas comunes de diseño.

En este artículo se presenta el concepto de patrones de diseño, su clasificación y un listado de los más comunes por cada tipo. Finalmente se muestra una comparativa entre dos patrones conocidos que son: Factory Method y Abstract Factory.

Definición

Un patrón de diseño es un tipo de estándar desarrollo que se aplica a problemas que ocurren comúnmente en el ámbito de desarrollo de software. Es una solución probada, expresiva y fácil de mantener; que proporciona una guía o plantilla para resolver un problema y puede ser utilizada en diferentes situaciones.

Tipos de patrones

Según la finalidad del patrón, estos se clasifican en tres tipos:

1.- Patrones creacionales

Se usan para instanciar objetos, separando la implementación del cliente de la de los objetos que se utilizan. Así, intentamos separar la lógica de creación de objetos y encapsularla. A continuación se presenta una lista con la descripción de los patrones más conocidos de este tipo:

  • Builder: Separa la creación de un objeto complejo de su estructura. De este modo, el mismo proceso de construcción sirve para crear representaciones diferentes.
  • Prototype: Utiliza plantillas para la creación de objetos. Este patrón especifica la clase de objetos a crear a partir de la clonación de uno ya creado.
  • Singleton: Limita a uno el número de instancias posibles de una clase en nuestro programa y proporciona un acceso global al mismo.
  • Factory Method: Utiliza un método de creación, delegando en las subclases la implementación de este método.
  • Abstract Factory: Proporciona una interfaz para crear familias de objetos que dependen entre sí, sin especificar sus clases concretas.

2.- Patrones estructurales

Utilizados para crear clases u objetos incluidos dentro de estructuras más complejas. A continuación se presenta una lista con la descripción de los patrones más conocidos este tipo:

  • Chain of responsibility: Evita acoplar al emisor y receptor de una petición, dando la posibilidad a varios receptores de consumirlo. Cada receptor tiene la opción de consumir esa petición o pasárselo al siguiente dentro de la cadena.
  • State: Permite modificar la forma en que un objeto se comporta en tiempo de ejecución, basándose en su estado interno.
  • Interpreter: Define una representación para una gramática así como el mecanismo para evaluarla. El árbol de sintaxis del lenguaje se suele modelar mediante el patrón Composite.
  • Visitor: Permite separar el algoritmo de la estructura de datos que se utilizará para ejecutarlo. De esta forma se pueden añadir nuevas operaciones a estas estructuras sin necesidad de modificarlas.
  • Mediator: Objeto que encapsula cómo otro conjunto de objetos interactúan y se comunican entre sí.
  • Memento: Este patrón otorga la capacidad de restaurar un objeto a un estado anterior.
  • Observer: Los objetos son capaces de suscribirse a una serie de eventos que otro objetivo va a emitir y serán avisados cuando esto ocurra.
  • Strategy: Permite la selección del algoritmo que ejecuta cierta acción en tiempo de ejecución.
  • Template Method: Especifica el esqueleto de un algoritmo, permitiendo a las subclases definir cómo implementan el comportamiento real.
  • Command: Son objetos que encapsulan una acción y los parámetros que necesitan para ejecutarse.
  • Iterator: Se utiliza para poder movernos por los elementos de un conjunto de forma secuencial, sin necesidad de exponer su implementación específica.

3.- Patrones de comportamiento

Se utilizan a la hora de definir cómo las clases y los objetos interactúan entre ellos. A continuación se presenta una lista con la descripción de los patrones más conocidos de este tipo:

  • Proxy: Es una clase que funciona como interfaz hacia cualquier otra cosa: una conexión a Internet, un archivo en disco o cualquier otro recurso que sea costoso o imposible de duplicar.
  • Bridge: Desacopla una abstracción de su implementación, para que las dos puedan evolucionar de forma independiente.
  • Facade (fachada): Objeto que crea una interfaz simplificada para tratar con otra parte del código más compleja, de tal forma que simplifica y aísla su uso. Un ejemplo podría ser crear una fachada para tratar con la clase de una librería externa.
  • Adapter: Permite a dos clases con diferentes interfaces trabajar entre ellas, a través de un objeto intermedio con el que se comunican e interactúan.
  • Composite: Facilita la creación de estructuras de objetos en árbol, donde todos los elementos emplean una misma interfaz. Cada uno de ellos puede a su vez contener un listado de esos objetos o ser el último de esa rama.
  • Flyweight: Una gran cantidad de objetos comparte un mismo objeto con propiedades comunes con el fin de ahorrar memoria.
  • Decorator: Permite añadir funcionalidad extra a un objeto (de forma dinámica o estática) sin modificar el comportamiento del resto de objetos del mismo tipo.

Los patrones de diseño expuestos anteriormente proporcionan soluciones muy variadas al momento de crear nuestro código. Es importante mencionar que estas soluciones ya han sido probadas y es necesario analizar las necesidades de nuestro proyecto para saber cuál se adapta de mejor a sus requerimientos.

Factory Method vs. Abstract Factory

En este apartado tratamos de exponer las diferencias entre dos patrones de diseño, que son Factory Method y Abstract Factory. Primero se exponen individualmente cada uno de ellos, para después identificar sus diferencias.

Factory Method

Define una interfaz para crear objetos, pero deja que sean las subclases las que deciden qué clases instanciar.

Este patrón consta de dos clases principales que son el creador y producto. El creador necesita crear instancias de productos; pero el tipo concreto de producto no debe ser forzado en las subclases del creador, porque las posibles subclases del creador deben poder especificar subclases del producto para utilizar.

Diagrama de un Factory Method utilizando un único producto y diferentes creadores.

Un ejemplo práctico del Factory Method, podemos ilustrarlo mediante un programa para la administración de viajes. Para este caso, el producto único a crear es el viaje. Por otro lado, considere que existen diferentes tipos de viajes, marítimo y terrestre, donde cada uno de ellos necesita un creador concreto.

Diagrama de clases para ejemplificar la creación de viajes mediante el Factory Method

Abstract Factory

Proporciona una interfaz para crear familias de objetos que dependen entre sí, sin especificar sus clases concretas. Este patrón se utiliza cuando:

  • Un sistema debe ser independiente de cómo sus objetos son creados.
  • Un sistema debe ser ‘configurado’ con una cierta familia de productos.
  • Se necesita reforzar la noción de dependencia mutua entre ciertos objetos.

Los elementos que conforman el patrón Abstract Factory son los siguientes:

  • Fábrica Abstracta: Define un conjunto de métodos (interfaz) para la creación de productos abstractos.
  • Fábrica Concreta: Implementa la interfaz de la Fábrica Abstracta para la creación de los distintos productos concretos.
  • Producto Abstracto: Define la interfaz de los objetos de tipo Producto A/B.
  • Producto Concreto: Implementan su respectiva interfaz representando un producto concreto.
Diagrama general de un Abstract Factory con la relación entre los elementos de este patrón de diseño.

Un ejemplo práctico del Abstract Factory, podemos ilustrarlo mediante un programa para la administración de viajes. Para este caso partimos de una familia de productos acorde a los diferentes tipos de viajes. En este caso tenemos dos tipos de viajes, marítimos y terrestres, que comparten productos pero que se aplican de diferente manera.

Nuestros productos son el transporte y el destino. Cada uno tiene su producto concreto y se utilizarán en una fábrica concreta.

Comparativa

Como podemos ver, Factory Method y Abstract Factory trabajan productos concretos; sin embargo, la diferencia radica en que el primero trabaja con un producto único mientras el segundo maneja una familia. Abstract Factory es más complejo de implementar, puesto que tiene un nivel conceptual mucho más amplio.

Otra diferencia notable es el ámbito de ambos: Factory Method es un patrón de clase, mientras que Abstract Factory es de objeto.

En resumen, Factory Method permite la creación en tiempo de ejecución siendo transparente para un cliente las clases concretas requeridas; por otro lado Abstract Factory se adapta mejor cuando el proyecto tiene que crear varias familias de productos, sin exponer los detalles de implementación.

Conclusión

Un patrón de diseño en software resuelve problemas constantes en nuestro entorno, sin necesidad de implementar una solución diferente cada vez. Como se mostró en este artículo, existen variedad de patrones de diseño que representan soluciones exitosas y contrastadas a problemas comunes.

--

--