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,LinuxButtoniLinuxCheckbox. - Implementa les interfícies
GUIFactory,ButtoniCheckboxrespectivament.
- 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
TextFieldper 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
