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
iWordDocument
implementen la interfícieDocument
. - Classe Factory:
DocumentFactory
és una classe abstracta que defineix el mètodecrearDocument()
. - Subclasses Factory:
PdfDocumentFactory
iWordDocumentFactory
implementen el mètodecrearDocument()
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ètodeactualitzar()
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.
Curs de Patrons de Disseny de Programari
Mòdul 1: Introducció als Patrons de Disseny
- Què són els Patrons de Disseny?
- Història i Origen dels Patrons de Disseny
- Classificació dels Patrons de Disseny
- Avantatges i Desavantatges d'Usar Patrons de Disseny
Mòdul 2: Patrons Creacionals
Mòdul 3: Patrons Estructurals
Mòdul 4: Patrons de Comportament
- Introducció als Patrons de Comportament
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Mòdul 5: Aplicació de Patrons de Disseny
- Com Seleccionar el Patró Adequat
- Exemples Pràctics d'Ús de Patrons
- Patrons de Disseny en Projectes Reals
- Refactorització Usant Patrons de Disseny
Mòdul 6: Patrons de Disseny Avançats
- Patrons de Disseny en Arquitectures Modernes
- Patrons de Disseny en Microserveis
- Patrons de Disseny en Sistemes Distribuïts
- Patrons de Disseny en Desenvolupament Àgil