En el mundo del desarrollo de software, los patrones de diseño se clasifican en tres categorías principales: creacionales, estructurales y de comportamiento. Cada una de estas categorías aborda diferentes aspectos del diseño de software y proporciona soluciones específicas a problemas comunes. A continuación, exploraremos cada una de estas categorías en detalle.

  1. Patrones Creacionales

Los patrones creacionales se centran en la forma en que se crean los objetos. Estos patrones ayudan a hacer que el sistema sea independiente de cómo se crean, componen y representan los objetos. Los patrones creacionales más comunes son:

  1. Singleton: Garantiza que una clase tenga una única instancia y proporciona un punto de acceso global a ella.
  2. Factory Method: Define una interfaz para crear un objeto, pero deja que las subclases decidan qué clase instanciar.
  3. Abstract Factory: Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.
  4. Builder: Separa la construcción de un objeto complejo de su representación, permitiendo que el mismo proceso de construcción cree diferentes representaciones.
  5. Prototype: Permite crear nuevos objetos copiando una instancia existente, conocida como prototipo.

Ejemplo de Singleton en Java

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // Constructor privado para evitar instanciación externa
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

  1. Patrones Estructurales

Los patrones estructurales se ocupan de la composición de clases y objetos para formar estructuras más grandes. Estos patrones ayudan a garantizar que si una parte de un sistema cambia, el impacto en otras partes sea mínimo. Los patrones estructurales más comunes son:

  1. Adapter: Permite que clases con interfaces incompatibles trabajen juntas.
  2. Bridge: Desacopla una abstracción de su implementación para que ambas puedan variar independientemente.
  3. Composite: Permite tratar a los objetos individuales y a las composiciones de objetos de manera uniforme.
  4. Decorator: Añade responsabilidades adicionales a un objeto de manera dinámica.
  5. Facade: Proporciona una interfaz simplificada a un conjunto de interfaces en un subsistema.
  6. Flyweight: Utiliza el almacenamiento compartido para soportar eficientemente un gran número de objetos de grano fino.
  7. Proxy: Proporciona un sustituto o marcador de posición para otro objeto para controlar el acceso a él.

Ejemplo de Adapter en Java

// Interfaz objetivo
public interface Target {
    void request();
}

// Clase existente que necesita ser adaptada
public class Adaptee {
    public void specificRequest() {
        System.out.println("Llamada específica");
    }
}

// Adaptador que hace que Adaptee sea compatible con Target
public class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

  1. Patrones de Comportamiento

Los patrones de comportamiento se centran en la interacción y responsabilidad entre los objetos. Estos patrones ayudan a definir cómo los objetos se comunican entre sí. Los patrones de comportamiento más comunes son:

  1. Chain of Responsibility: Permite que varios objetos manejen una solicitud, pasando la solicitud a lo largo de una cadena de manejadores.
  2. Command: Encapsula una solicitud como un objeto, permitiendo parametrizar a los clientes con diferentes solicitudes, colas o registros de solicitudes.
  3. Interpreter: Dada un lenguaje, define una representación para su gramática junto con un intérprete que usa la representación para interpretar oraciones en el lenguaje.
  4. Iterator: Proporciona una forma de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación subyacente.
  5. Mediator: Define un objeto que encapsula cómo un conjunto de objetos interactúa.
  6. Memento: Sin violar la encapsulación, captura y externaliza el estado interno de un objeto para que el objeto pueda ser restaurado a este estado más tarde.
  7. Observer: Define una dependencia de uno a muchos entre objetos para que cuando un objeto cambie de estado, todos sus dependientes sean notificados y actualizados automáticamente.
  8. State: Permite a un objeto alterar su comportamiento cuando su estado interno cambia.
  9. Strategy: Define una familia de algoritmos, encapsula cada uno y los hace intercambiables.
  10. Template Method: Define el esqueleto de un algoritmo en una operación, diferiendo algunos pasos a las subclases.
  11. Visitor: Representa una operación que se va a realizar en los elementos de una estructura de objetos.

Ejemplo de Observer en Java

import java.util.ArrayList;
import java.util.List;

// Interfaz de observador
interface Observer {
    void update(String message);
}

// Clase sujeto
class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

// Implementación de un observador
class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " recibió el mensaje: " + message);
    }
}

// Uso del patrón Observer
public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        Observer observer1 = new ConcreteObserver("Observador 1");
        Observer observer2 = new ConcreteObserver("Observador 2");

        subject.addObserver(observer1);
        subject.addObserver(observer2);

        subject.notifyObservers("Hola Observadores!");
    }
}

Conclusión

En esta sección, hemos explorado las tres categorías principales de patrones de diseño: creacionales, estructurales y de comportamiento. Cada categoría aborda diferentes aspectos del diseño de software y proporciona soluciones específicas a problemas comunes. Comprender estas categorías y los patrones individuales dentro de ellas es fundamental para aplicar patrones de diseño de manera efectiva en el desarrollo de software. En los próximos módulos, profundizaremos en cada uno de estos patrones con ejemplos prácticos y ejercicios para reforzar el aprendizaje.

© Copyright 2024. Todos los derechos reservados