En aquesta secció, explorarem exemples pràctics de com els patrons de disseny es poden aplicar en situacions reals de desenvolupament de programari. Cada exemple inclourà una explicació del problema, la solució proporcionada pel patró de disseny, i un fragment de codi per il·lustrar la implementació.

Exemple 1: Singleton

Problema

Necessitem assegurar-nos que una classe només tingui una única instància i proporcionar un punt d'accés global a aquesta instància. Un exemple comú és la gestió de la configuració d'una aplicació.

Solució

El patró Singleton garanteix que una classe només tingui una única instància i proporciona un punt d'accés global a aquesta instància.

Implementació en Java

public class Configuracio {
    private static Configuracio instancia;
    private Properties propietats;

    private Configuracio() {
        propietats = new Properties();
        // Carregar propietats des d'un fitxer o una font de dades
    }

    public static Configuracio getInstancia() {
        if (instancia == null) {
            instancia = new Configuracio();
        }
        return instancia;
    }

    public String getPropietat(String clau) {
        return propietats.getProperty(clau);
    }
}

Explicació

  1. Constructor Privat: El constructor és privat per evitar la creació d'instàncies externes.
  2. Mètode Estàtic: getInstancia() proporciona un punt d'accés global a la instància única.
  3. Instància Única: La instància es crea només quan es necessita per primera vegada.

Exercici Pràctic

Implementa un Singleton per gestionar la connexió a una base de dades.

Exemple 2: Factory Method

Problema

Volem crear objectes sense especificar la classe exacta de l'objecte que serà creat. Un exemple comú és la creació de diferents tipus de documents (PDF, Word, etc.).

Solució

El patró Factory Method defineix una interfície per crear un objecte, però permet que les subclasses decideixin quina classe instanciar.

Implementació en Java

abstract class Document {
    public abstract void obrir();
}

class PDFDocument extends Document {
    public void obrir() {
        System.out.println("Obrint document PDF");
    }
}

class WordDocument extends Document {
    public void obrir() {
        System.out.println("Obrint document Word");
    }
}

abstract class DocumentFactory {
    public abstract Document crearDocument();
}

class PDFDocumentFactory extends DocumentFactory {
    public Document crearDocument() {
        return new PDFDocument();
    }
}

class WordDocumentFactory extends DocumentFactory {
    public Document crearDocument() {
        return new WordDocument();
    }
}

Explicació

  1. Classe Abstracta Document: Defineix una interfície comuna per a tots els documents.
  2. Subclasses Concretes: PDFDocument i WordDocument implementen la interfície Document.
  3. Classe Abstracta DocumentFactory: Defineix el mètode crearDocument().
  4. Subclasses Concretes de Factory: PDFDocumentFactory i WordDocumentFactory implementen el mètode crearDocument() per crear instàncies de PDFDocument i WordDocument, respectivament.

Exercici Pràctic

Implementa una fàbrica per crear diferents tipus de vehicles (cotxe, moto, camió).

Exemple 3: Observer

Problema

Necessitem notificar múltiples objectes quan l'estat d'un altre objecte canvia. Un exemple comú és un sistema de notificacions.

Solució

El patró Observer defineix una dependència un-a-molts entre objectes, de manera que quan un objecte canvia el seu estat, tots els seus dependents són notificats i actualitzats automàticament.

Implementació en Java

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

interface Observer {
    void actualitzar(String missatge);
}

class Subject {
    private List<Observer> observadors = new ArrayList<>();

    public void afegirObservador(Observer observador) {
        observadors.add(observador);
    }

    public void eliminarObservador(Observer observador) {
        observadors.remove(observador);
    }

    public void notificarObservadors(String missatge) {
        for (Observer observador : observadors) {
            observador.actualitzar(missatge);
        }
    }
}

class ObservadorConcret implements Observer {
    private String nom;

    public ObservadorConcret(String nom) {
        this.nom = nom;
    }

    public void actualitzar(String missatge) {
        System.out.println(nom + " ha rebut el missatge: " + missatge);
    }
}

Explicació

  1. Interfície Observer: Defineix el mètode actualitzar() que serà cridat per notificar els observadors.
  2. Classe Subject: Manté una llista d'observadors i proporciona mètodes per afegir, eliminar i notificar observadors.
  3. Classe ObservadorConcret: Implementa la interfície Observer i defineix el comportament quan es rep una notificació.

Exercici Pràctic

Implementa un sistema de notificacions per a una aplicació de missatgeria on els usuaris poden subscriure's a diferents canals.

Conclusió

Els patrons de disseny proporcionen solucions provades per a problemes comuns en el desenvolupament de programari. A través d'aquests exemples pràctics, hem vist com els patrons Singleton, Factory Method i Observer poden ser aplicats per resoldre problemes reals. Practicar la implementació d'aquests patrons en diferents contextos ajudarà a consolidar la comprensió i habilitat per utilitzar-los de manera efectiva en projectes futurs.

Exercicis Addicionals

  1. Implementa el patró Decorator per afegir funcionalitats addicionals a un objecte de manera dinàmica.
  2. Utilitza el patró Strategy per permetre que una classe pugui utilitzar diferents algorismes de manera intercanviable.
  3. Aplica el patró Composite per tractar objectes individuals i composicions d'objectes de manera uniforme.
© Copyright 2024. Tots els drets reservats