🔨 Patrones de diseño
⚡ ¿Estás listo para llevar tus habilidades de programación al siguiente nivel?
Este repositorio es el lugar perfecto para aprender sobre los patrones de diseño más utilizados en la programación, con enfoque en Kotlin.
💡 Descubre cómo solucionar problemas comunes y mejorar la calidad de tu código con la ayuda de ejemplos concretos de código, diagramas de clases y explicaciones detalladas de cada patrón.
Índice
Introducción
En esta sección, proporcionaremos una introducción breve sobre patrones de diseño, su importancia y los diferentes tipos de patrones que existen.
Los patrones de diseño son soluciones estandarizadas a problemas que surgen en el desarrollo de programas. Estos patrones nos ayudan a estructurar el código de una manera que sea fácil de entender, de escalar y mantener. Existen diferentes categorias de patrones de diseño como por ejemplo:
Patrones de creación
Los patrones de creación son aquellos que se centran en la creación de objetos. En esta sección, presentamos los diferentes patrones de creación y su implementación en diferentes lenguajes de programación.
Singleton
El patrón Singleton es un patrón de diseño creacional que se utiliza para crear una única instancia de una clase y que esta tenga un acceso global. Este quizá sea una de los patrones más fáciles de implementar, pero hay que tener sumo cuidado de no abusar del mismo.
Definición
El patrón Singleton es uno de los patrones de diseño creacionales más comunes en la programación orientada a objetos. Sus principales elementos son los siguientes:
| Singleton: es la clase que se asegura de que solo haya una instancia de sí misma en todo el sistema. Controla el acceso a esa instancia única mediante un método estático que devuelve la instancia. |
|---|
| Constructor privado: es un constructor que se define como privado para evitar que se cree una instancia de la clase fuera de la propia clase. |
| Método estático de instancia única (Singleton): es el método que devuelve la única instancia de la clase Singleton. Se suele implementar como un método estático que devuelve la instancia única, creándola si no existe previamente. |
Uso
El patrón Singleton se puede utilizar en situaciones donde se necesita garantizar que sólo exista una instancia de una clase en todo el programa, y que esta instancia sea fácilmente accesible desde cualquier parte del mismo. Algunos casos donde se puede utilizar son:
- En aplicaciones de registro
- En aplicaciones de manejo de configuraciones
- En aplicaciones de acceso a bases de datos
Implementación
Para implementar correctamente el patrón Singleton, es necesario seguir los siguientes pasos:
- Crear una clase que contenga la instancia del objeto que queremos que sea único y privado. Este objeto debe ser estático, es decir, pertenecer a la clase y no a una instancia particular de la misma.
- Crear un constructor privado para la clase, de manera que la instancia solo pueda ser creada desde la propia clase.
- Crear un método público estático que permita acceder a la instancia de la clase. Si la instancia no ha sido creada todavía, este método debe crearla y devolverla. Si ya existe, debe devolver la instancia ya creada.
- Asegurarse de que la clase es segura para ser utilizada en un entorno multihilo. Para ello, es necesario utilizar técnicas de sincronización que eviten que varias instancias de la clase sean creadas al mismo tiempo.
Factory Method
El Factory Method es un patrón de diseño creacional que proporciona una forma de delegar la lógica de creación de instancias a objetos secundarios. Aquí, el usuario final no se preocupa por la lógica de creación del objeto. Normalmente, se puede hacer uso de este patrón cuando se posee una superclase y esta posee múltiples subclases, para devolver una de las subclases según sea el requerimiento del usuario final.
¿Cuándo se puede usar este patrón?
- Cuando una clase no sabe qué subclases se requerirán para crear.
- Cuando una clase quiere que sus subclases especifiquen los objetos a crear.
- Cuando las clases padres eligen la creación de objetos para sus subclases.

Definción de casa elemento
| Elemento | Descripción |
|---|
| Product | Es una interfaz o clase abstracta que define el tipo de objetos que puede crear el Factory y sus subclases. |
| ConcreteProduct | Son las implementaciones concretas de la interfaz o clase abstracta Product. |
| Creator | Es una clase abstracta que define un método abstracto para la creación de objetos del tipo Product, que las subclases deben implementar. |
| ConcreteCreator | Son las subclases concretas que implementan el método abstracto definido en Creator y crean objetos del tipo ConcreteProduct. |
Factory Method y Abstract Factory
El patrón Factory Method y el patrón Abstract Factory pueden parecer similares en algunos aspectos, lo que puede llevar a cierta confusión. Aquí hay algunas razones por las que se pueden confundir:
- Ambos patrones son creacionales y se utilizan para crear objetos. El patrón Factory Method crea objetos a través de una interfaz común, mientras que el patrón Abstract Factory crea objetos relacionados por familias.
- En ambos patrones, el cliente no sabe qué clase concreta está instanciando. En el patrón Factory Method, la creación de objetos se delega a las subclases, y en el patrón Abstract Factory, la creación de objetos se delega a una fábrica abstracta.
- Ambos patrones son útiles para crear objetos que sean compatibles entre sí. El patrón Factory Method garantiza que todos los objetos creados sean del mismo tipo, mientras que el patrón Abstract Factory garantiza que los objetos creados sean compatibles entre sí.
A continuación, se presenta una tabla comparativa entre el patrón de diseño Factory Method y Abstract Factory:
Tabla comparativa entre el patrón de diseño Factory Method y Abstract Factory
| Factoría de Métodos (Factory Method) | Factoría Abstracta (Abstract Factory) |
|---|
| Define una interfaz para crear un objeto de forma que las subclases puedan decidir qué clase implementar. | Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. |
| Es utilizado para crear un solo producto. | Es utilizado para crear múltiples productos relacionados. |
| La subclase determina la clase concreta a instanciar. | La subclase determina la factoría concreta a utilizar. |
| Es una solución más simple y fácil de entender. | Es una solución más compleja pero más flexible y escalable. |
| Útil cuando se tiene un conjunto conocido de tipos de objetos que deben ser creados. | Útil cuando se tiene un conjunto de tipos de objetos que deben ser creados y hay una dependencia entre ellos. |
Abstract Factory
El patrón de diseño Abstract Factory es un patrón creacional que proporciona una interfaz para crear familias de objetos relacionados sin especificar su clase concreta. Es decir, permite crear objetos de diferentes tipos relacionados entre sí, sin conocer la implementación específica de cada uno. Esto permite que la aplicación sea más flexible y escalable, ya que los objetos pueden ser intercambiados sin afectar al resto del sistema.
Este patron se puede pensar como una fábrica de coches, donde hay varias fábricas de coches (fábricas concretas) que producen diferentes tipos de coches (productos concretos). Cada fábrica de coches tiene su propia línea de producción especializada en ciertos tipos de coches. Por ejemplo, una fábrica puede producir coches deportivos mientras que otra puede producir coches familiares.
Ventajas de su uso
-
Proporciona una forma de crear objetos relacionados sin especificar sus clases concretas. Esto permite desacoplar el código cliente de la creación de objetos, lo que facilita la modificación y extensión del sistema.
-
Permite intercambiar fácilmente entre diferentes familias de objetos, ya que cada fábrica concreta implementa una interfaz común para crear objetos abstractos. Esto hace que el código sea más flexible y fácil de mantener.
-
Favorece el principio de "abrir/cerrar" (Open/Closed), que es uno de los principios fundamentales de la programación orientada a objetos. Esto significa que el código es abierto para extensión, pero cerrado para modificación, lo que hace que sea más fácil añadir nuevas funcionalidades al sistema sin tener que modificar el código existente.
-
Promueve la coherencia y la consistencia en el diseño de la aplicación. Al utilizar el patrón Abstract Factory, se asegura que todos los objetos creados por una fábrica concreta pertenecen a la misma familia y tienen una coherencia y consistencia en su diseño.
Definición de cada elemento
| Elemento | Descripción |
|---|
| Abstract Factory | Define una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. |
| Concrete Factory | Implementa la interfaz de la fábrica abstracta para crear objetos de una familia concreta. |
| Abstract Product | Define una interfaz para un tipo de objeto que forma parte de la familia de objetos que puede crear la fábrica abstracta. |
| Concrete Product | Implementa la interfaz de un producto abstracto para crear objetos de un tipo concreto. |
| Client | Usa únicamente las interfaces declaradas por Abstract Factory y Abstract Product para interactuar con objetos de la familia de productos. |
¿Cuando usar este patrón?
- Cuando se necesitan crear objetos que tengan una interfaz común, pero que varíen en la implementación.
- Cuando se necesitan crear objetos que estén relacionados entre sí, como por ejemplo diferentes tipos de objetos que interactúan entre sí en un juego.
- Cuando se desea ocultar la complejidad de la creación de objetos al cliente, por ejemplo al crear diferentes implementaciones de un objeto a partir de una fábrica abstracta sin que el cliente necesite conocer los detalles de cada implementación.
- Cua