En aquest tema, explorarem com els patrons de disseny es poden aplicar en projectes reals. Veurem exemples concrets de com aquests patrons ajuden a resoldre problemes comuns en el desenvolupament de programari, millorant la mantenibilitat, escalabilitat i flexibilitat del codi.

Objectius del Tema

  • Entendre com aplicar patrons de disseny en situacions reals.
  • Aprendre a identificar problemes comuns que es poden resoldre amb patrons de disseny.
  • Veure exemples pràctics de patrons de disseny en acció.

Exemples Pràctics

Exemple 1: Singleton en la Configuració d'una Aplicació

Descripció del Problema

En una aplicació gran, és comú tenir una classe de configuració que conté paràmetres globals com ara connexions a bases de dades, configuracions de xarxa, etc. És important assegurar-se que només hi hagi una instància d'aquesta classe per evitar inconsistències.

Solució amb Singleton

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

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

    private Configuracio() {
        // Carregar propietats des d'un fitxer
        propietats = new Properties();
        try {
            propietats.load(new FileInputStream("config.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

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

Explicació

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

Exemple 2: Factory Method per a la Creació d'Objectes

Descripció del Problema

Suposem que estem desenvolupant una aplicació que necessita crear diferents tipus de documents (PDF, Word, Excel). La creació d'aquests documents pot variar, però volem encapsular la lògica de creació per mantenir el codi net i fàcil de mantenir.

Solució amb Factory Method

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

// Interfície Document
public interface Document {
    void obrir();
    void tancar();
}

// Implementacions concretes
public class PdfDocument implements Document {
    public void obrir() {
        System.out.println("Obrint document PDF");
    }
    public void tancar() {
        System.out.println("Tancant document PDF");
    }
}

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

// Classe Factory
public abstract class DocumentFactory {
    public abstract Document crearDocument();
}

public class PdfDocumentFactory extends DocumentFactory {
    public Document crearDocument() {
        return new PdfDocument();
    }
}

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

Explicació

  • Interfície Document: Defineix les operacions comunes per a tots els documents.
  • Classes Concretes: PdfDocument i WordDocument implementen la interfície Document.
  • Classe Factory: DocumentFactory és una classe abstracta que defineix el mètode crearDocument().
  • Subclasses Factory: PdfDocumentFactory i WordDocumentFactory implementen el mètode crearDocument() per crear instàncies concretes.

Exemple 3: Observer per a la Gestió d'Esdeveniments

Descripció del Problema

En una aplicació GUI, és comú tenir diversos components que necessiten ser notificats quan ocorre un esdeveniment, com ara un botó que es prem. Volem una manera eficient de gestionar aquestes notificacions sense crear dependències fortes entre els components.

Solució amb Observer

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

// Interfície Observer
public interface Observer {
    void actualitzar();
}

// Interfície Subject
public interface Subject {
    void afegirObserver(Observer o);
    void eliminarObserver(Observer o);
    void notificarObservers();
}

// Implementació Subject
public class Botó implements Subject {
    private List<Observer> observers = new ArrayList<>();

    public void afegirObserver(Observer o) {
        observers.add(o);
    }

    public void eliminarObserver(Observer o) {
        observers.remove(o);
    }

    public void notificarObservers() {
        for (Observer o : observers) {
            o.actualitzar();
        }
    }

    public void premer() {
        System.out.println("Botó premut");
        notificarObservers();
    }
}

// Implementació Observer
public class BotóListener implements Observer {
    public void actualitzar() {
        System.out.println("BotóListener notificat");
    }
}

Explicació

  • Interfície Observer: Defineix el mètode actualitzar() que serà cridat quan el subjecte canviï d'estat.
  • Interfície Subject: Defineix mètodes per afegir, eliminar i notificar observadors.
  • Implementació Subject: Botó manté una llista d'observadors i els notifica quan es prem el botó.
  • Implementació Observer: BotóListener implementa el mètode actualitzar() per rebre notificacions.

Resum

En aquesta secció, hem vist com aplicar alguns dels patrons de disseny més comuns en projectes reals. Els patrons Singleton, Factory Method i Observer són només alguns exemples de com podem utilitzar aquests patrons per resoldre problemes comuns en el desenvolupament de programari. A mesura que guanyis experiència, trobaràs que aquests patrons es converteixen en eines valuoses en el teu arsenal de desenvolupador.

En el següent tema, explorarem com seleccionar el patró adequat per a diferents situacions.

© Copyright 2024. Tots els drets reservats