Patrones de Diseño GOF (Gang of Four)
Los Patrones de Diseño de la "Gang of Four" (GOF) son una colección de soluciones comunes a problemas recurrentes en el diseño de software orientado a objetos. Estos patrones permiten mejorar la estructura y la flexibilidad del código, haciendo que las aplicaciones sean más fáciles de mantener y extender a lo largo del tiempo. En este post vamos a explicar qué son los patrones GOF, sus tres categorías principales, y ofrecer un vistazo general a los patrones dentro de cada una de esas categorías.
¿Qué son los Patrones de Diseño GOF?
Los patrones GOF fueron introducidos en el famoso libro "Design Patterns: Elements of Reusable Object-Oriented Software", escrito en 1994 por Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, conocidos como la "Gang of Four" (GOF). La idea detrás de estos patrones es proporcionar soluciones reutilizables que puedan ser aplicadas a problemas de diseño comunes, ahorrando tiempo y esfuerzo a los desarrolladores.
Es importante recalcar que los patrones de diseño no son soluciones preconstruidas que puedas copiar y pegar en tu código, sino más bien, son enfoques que te guían hacia una mejor arquitectura.
Tipos de Patrones de Diseño
Existen tres tipos principales de patrones de diseño en la clasificación de la GOF: Creacionales, Estructurales y De Comportamiento. Cada uno aborda una faceta distinta del diseño de software.
1. Patrones Creacionales
Los patrones creacionales se centran en la forma en que los objetos son creados. Su objetivo es evitar la creación directa de objetos con "new", proporcionando formas más flexibles de crear instancias y gestionar la construcción de estos objetos. Aquí tienes una lista de los patrones creacionales más importantes:
- Factory Method: Proporciona una interfaz para crear objetos, pero deja que las subclases decidan cuál es la clase a instanciar.
- Abstract Factory: Crea familias de objetos relacionados sin especificar sus clases concretas.
- Builder: Separa la construcción de un objeto complejo de su representación, permitiendo crear diferentes representaciones.
- Prototype: Permite la creación de nuevos objetos copiando una instancia existente (clonación).
- Singleton: Garantiza que una clase solo tenga una instancia, y proporciona un punto de acceso global a esa instancia.
🔎 Ejemplo de Singleton en Java
// Ejemplo de patron Singleton
public class Singleton {private static Singleton instance;private Singleton() {// Constructor privado}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
En este ejemplo, el patrón Singleton garantiza que siempre haya una única instancia de la clase "Singleton"
. Si alguna vez has tenido que trabajar con recursos que no deben tener más de una instancia (por ejemplo, una conexión a una base de datos), este patrón es clave.
2. Patrones Estructurales
Los patrones estructurales se ocupan de la composición de las clases y objetos, es decir, de cómo se pueden combinar objetos para formar estructuras más grandes y flexibles. Su objetivo es facilitar las relaciones entre entidades sin modificar sus interfaces.
- Adapter: Permite que dos interfaces incompatibles trabajen juntas.
- Bridge: Desacopla una abstracción de su implementación para que ambas puedan evolucionar independientemente.
- Composite: Permite tratar objetos individuales y composiciones de objetos de manera uniforme.
- Decorator: Añade responsabilidades adicionales a un objeto de manera dinámica.
- Facade: Proporciona una interfaz simplificada para un sistema de clases.
- Flyweight: Minimiza el uso de memoria compartiendo tantos datos como sea posible con objetos similares.
- Proxy: Proporciona un sustituto o marcador de posición para otro objeto para controlar el acceso a este.
🔎 Ejemplo de Facade en Java
// Ejemplo de patron Facade
class CPU {void start() { System.out.println("CPU arrancada"); }}class Memory {void load() { System.out.println("Memoria cargada"); }}class ComputerFacade {private CPU cpu;private Memory memory;public ComputerFacade() {this.cpu = new CPU();this.memory = new Memory();}public void start() {cpu.start();memory.load();System.out.println("Maquina iniciada");}}public class Main {public static void main(String[] args) {ComputerFacade computer = new ComputerFacade();computer.start();}}
En este caso, el patrón Facade oculta la complejidad del sistema de arranque del ordenador (la CPU y la memoria) detrás de una interfaz simple.
3. Patrones de Comportamiento
Los patrones de comportamiento se centran en la comunicación entre objetos, la forma en que interactúan y se delegan responsabilidades. Estos patrones facilitan las interacciones complejas, pero de manera flexible y reutilizable.
- Chain of Responsibility: Pasa una solicitud a lo largo de una cadena de gestores hasta que uno de ellos la procese.
- Command: Encapsula una solicitud como un objeto, permitiendo parametrizar a los clientes con diferentes solicitudes.
- Interpreter: Proporciona una manera de evaluar sentencias en un lenguaje.
- Iterator: Proporciona una manera de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación interna.
- Mediator: Reduce la complejidad de la comunicación entre múltiples objetos al centralizarla en un solo objeto mediador.
- Memento: Permite capturar y restaurar el estado de un objeto sin violar su encapsulamiento.
- Observer: Define una dependencia uno a muchos entre objetos, de modo que cuando uno cambie de estado, todos sus dependientes sean notificados.
- State: Permite que un objeto altere su comportamiento cuando su estado interno cambia.
- Strategy: Permite seleccionar un algoritmo en tiempo de ejecución.
- Template Method: Define el esqueleto de un algoritmo en una operación, dejando algunos pasos para que las subclases los implementen.
- Visitor: Representa una operación que se realiza sobre los elementos de una estructura de objetos.
🔎 Ejemplo de Observer en Java
// Ejemplo de patron Observer
interface Observer {void update(String message);}class ConcreteObserver implements Observer {@Overridepublic void update(String message) {System.out.println("Recibido: " + message);}}class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) {observers.add(observer);}public void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}}
Este ejemplo demuestra cómo funciona el patrón Observer, donde múltiples observadores pueden suscribirse a un sujeto y ser notificados cuando el estado del sujeto cambia.
Conclusión
Los Patrones de Diseño GOF son herramientas robustas que permiten a los desarrolladores crear software más estructurado, reutilizable y fácil de mantener. Cada tipo de patrón (creacional, estructural o de comportamiento) aborda diferentes aspectos del diseño de software, desde la creación de objetos hasta la forma en que interactúan entre sí. Entender y aplicar estos patrones no solo mejora la calidad del código, sino que también facilita el trabajo en equipo y la escalabilidad de las aplicaciones.
Recuerda, los patrones son guías, no soluciones rígidas. Siempre deben adaptarse al contexto y a las necesidades específicas de tu proyecto.
¡Nos vemos en el siguiente post!
Saludos.
Comentarios
Publicar un comentario