Introducció
El patró Abstract Factory és un patró creacional que proporciona una interfície per crear famílies d'objectes relacionats o dependents sense especificar les seves classes concretes. Aquest patró és útil quan el sistema ha de ser independent de com es creen, componen i representen els seus objectes.
Objectius del Patró Abstract Factory
- Proporcionar una interfície per crear famílies d'objectes relacionats.
- Permetre que els clients utilitzin objectes sense conèixer les seves classes concretes.
- Facilitar l'intercanvi d'objectes fàcilment.
Estructura
L'estructura del patró Abstract Factory inclou els següents components:
- AbstractFactory: Declara una interfície per a les operacions que creen objectes abstractes.
- ConcreteFactory: Implementa les operacions per crear objectes concrets.
- AbstractProduct: Declara una interfície per a un tipus d'objecte producte.
- ConcreteProduct: Defineix un objecte producte que serà creat per la fàbrica concreta corresponent.
- Client: Utilitza només les interfícies declarades per AbstractFactory i AbstractProduct.
Diagrama UML
+------------------+ +------------------+ | AbstractFactory |<-------->| ConcreteFactory | +------------------+ +------------------+ | +createProductA()| | +createProductA()| | +createProductB()| | +createProductB()| +------------------+ +------------------+ ^ ^ | | | | +------------------+ +------------------+ | AbstractProductA| | ConcreteProductA| +------------------+ +------------------+ | +operation() | | +operation() | +------------------+ +------------------+ ^ ^ | | | | +------------------+ +------------------+ | AbstractProductB| | ConcreteProductB| +------------------+ +------------------+ | +operation() | | +operation() | +------------------+ +------------------+
Exemple Pràctic
Escenari
Suposem que estem desenvolupant una aplicació que ha de funcionar en diferents sistemes operatius (Windows i Mac). Necessitem crear interfícies d'usuari específiques per a cada sistema operatiu.
Implementació
1. Definició de les interfícies abstractes
// Abstract Factory public interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } // Abstract Product A public interface Button { void paint(); } // Abstract Product B public interface Checkbox { void paint(); }
2. Implementació de les fàbriques concretes
// Concrete Factory 1 public class WindowsFactory implements GUIFactory { @Override public Button createButton() { return new WindowsButton(); } @Override public Checkbox createCheckbox() { return new WindowsCheckbox(); } } // Concrete Factory 2 public class MacFactory implements GUIFactory { @Override public Button createButton() { return new MacButton(); } @Override public Checkbox createCheckbox() { return new MacCheckbox(); } }
3. Implementació dels productes concrets
// Concrete Product A1 public class WindowsButton implements Button { @Override public void paint() { System.out.println("Rendering a button in Windows style."); } } // Concrete Product A2 public class MacButton implements Button { @Override public void paint() { System.out.println("Rendering a button in Mac style."); } } // Concrete Product B1 public class WindowsCheckbox implements Checkbox { @Override public void paint() { System.out.println("Rendering a checkbox in Windows style."); } } // Concrete Product B2 public class MacCheckbox implements Checkbox { @Override public void paint() { System.out.println("Rendering a checkbox in Mac style."); } }
4. Utilització del patró Abstract Factory
public class Application { private Button button; private Checkbox checkbox; public Application(GUIFactory factory) { button = factory.createButton(); checkbox = factory.createCheckbox(); } public void paint() { button.paint(); checkbox.paint(); } } public class Demo { private static Application configureApplication() { Application app; GUIFactory factory; String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("mac")) { factory = new MacFactory(); } else { factory = new WindowsFactory(); } app = new Application(factory); return app; } public static void main(String[] args) { Application app = configureApplication(); app.paint(); } }
Exercicis Pràctics
Exercici 1: Implementació d'una Fàbrica per a Linux
- Descripció: Implementa una fàbrica concreta per a Linux que creï botons i caselles de verificació en estil Linux.
- Passos:
- Crea les classes
LinuxFactory
,LinuxButton
iLinuxCheckbox
. - Implementa les interfícies
GUIFactory
,Button
iCheckbox
respectivament.
- Crea les classes
Solució
// Concrete Factory 3 public class LinuxFactory implements GUIFactory { @Override public Button createButton() { return new LinuxButton(); } @Override public Checkbox createCheckbox() { return new LinuxCheckbox(); } } // Concrete Product A3 public class LinuxButton implements Button { @Override public void paint() { System.out.println("Rendering a button in Linux style."); } } // Concrete Product B3 public class LinuxCheckbox implements Checkbox { @Override public void paint() { System.out.println("Rendering a checkbox in Linux style."); } }
Exercici 2: Afegir un Nou Tipus de Producte
- Descripció: Afegiu un nou tipus de producte,
TextField
, a les fàbriques existents. - Passos:
- Defineix la interfície
TextField
. - Implementa
TextField
per a Windows, Mac i Linux. - Actualitza les fàbriques per crear
TextField
.
- Defineix la interfície
Solució
// Abstract Product C public interface TextField { void render(); } // Concrete Product C1 public class WindowsTextField implements TextField { @Override public void render() { System.out.println("Rendering a text field in Windows style."); } } // Concrete Product C2 public class MacTextField implements TextField { @Override public void render() { System.out.println("Rendering a text field in Mac style."); } } // Concrete Product C3 public class LinuxTextField implements TextField { @Override public void render() { System.out.println("Rendering a text field in Linux style."); } } // Update Factories public interface GUIFactory { Button createButton(); Checkbox createCheckbox(); TextField createTextField(); // New method } public class WindowsFactory implements GUIFactory { @Override public Button createButton() { return new WindowsButton(); } @Override public Checkbox createCheckbox() { return new WindowsCheckbox(); } @Override public TextField createTextField() { return new WindowsTextField(); } } public class MacFactory implements GUIFactory { @Override public Button createButton() { return new MacButton(); } @Override public Checkbox createCheckbox() { return new MacCheckbox(); } @Override public TextField createTextField() { return new MacTextField(); } } public class LinuxFactory implements GUIFactory { @Override public Button createButton() { return new LinuxButton(); } @Override public Checkbox createCheckbox() { return new LinuxCheckbox(); } @Override public TextField createTextField() { return new LinuxTextField(); } }
Resum
El patró Abstract Factory és una eina poderosa per crear famílies d'objectes relacionats sense dependre de les seves classes concretes. Aquest patró és especialment útil quan es treballa amb sistemes que han de ser independents de la plataforma o quan es necessita intercanviar fàcilment diferents implementacions d'objectes. Hem vist com implementar aquest patró amb un exemple pràctic i hem proporcionat exercicis per reforçar els conceptes apresos.
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