Introducció
El patró Factory Method és un patró de disseny creacional que proporciona una interfície per crear objectes en una superclasse, però permet que les subclasses alterin el tipus d'objectes que es crearan. Aquest patró és útil quan la creació de l'objecte implica una lògica complexa o quan el tipus d'objecte a crear no es coneix fins al moment de l'execució.
Objectius del Patró Factory Method
- Encapsular la Creació d'Objectes: Permet encapsular la lògica de creació d'objectes dins d'un mètode, fent que el codi sigui més modular i fàcil de mantenir.
- Flexibilitat: Facilita la substitució de subclasses sense modificar el codi existent.
- Reduir la Dependència: Minimitza la dependència entre les classes, promovent un disseny més desacoblat.
Estructura del Patró Factory Method
El patró Factory Method consta de les següents parts:
- Producte: Defineix la interfície dels objectes que la fàbrica crearà.
- Producte Concret: Implementa la interfície del producte.
- Creador: Declara el mètode de fàbrica que retorna un objecte de tipus Producte.
- Creador Concret: Implementa el mètode de fàbrica per crear un objecte de Producte Concret.
Diagrama UML
+------------------+ +------------------+ | Creator | | ConcreteCreator| +------------------+ +------------------+ | + factoryMethod()|<------| + factoryMethod() | +------------------+ +------------------+ ^ ^ | | | | +------------------+ +------------------+ | Product | | ConcreteProduct | +------------------+ +------------------+ | + operation() | | + operation() | +------------------+ +------------------+
Exemple Pràctic
A continuació, es presenta un exemple pràctic del patró Factory Method en Python:
Interfície del Producte
from abc import ABC, abstractmethod class Transport(ABC): @abstractmethod def deliver(self) -> str: pass
Productes Concrets
class Truck(Transport): def deliver(self) -> str: return "Deliver by land in a box" class Ship(Transport): def deliver(self) -> str: return "Deliver by sea in a container"
Creador
class Logistics(ABC): @abstractmethod def create_transport(self) -> Transport: pass def plan_delivery(self) -> str: transport = self.create_transport() return transport.deliver()
Creadors Concrets
class RoadLogistics(Logistics): def create_transport(self) -> Transport: return Truck() class SeaLogistics(Logistics): def create_transport(self) -> Transport: return Ship()
Client
def client_code(logistics: Logistics) -> None: print(f"Client: {logistics.plan_delivery()}") if __name__ == "__main__": print("App: Launched with the RoadLogistics.") client_code(RoadLogistics()) print("\nApp: Launched with the SeaLogistics.") client_code(SeaLogistics())
Explicació del Codi
- Interfície del Producte:
Transport
és una classe abstracta que defineix el mètodedeliver
. - Productes Concrets:
Truck
iShip
són implementacions concretes deTransport
. - Creador:
Logistics
és una classe abstracta que declara el mètode de fàbricacreate_transport
i un altre mètodeplan_delivery
que utilitza el producte creat. - Creadors Concrets:
RoadLogistics
iSeaLogistics
implementen el mètode de fàbrica per crear instàncies deTruck
iShip
, respectivament. - Client: El client utilitza el creador concret per planificar la entrega.
Exercici Pràctic
Enunciat
Implementa un sistema de notificacions que utilitzi el patró Factory Method. El sistema ha de poder enviar notificacions per correu electrònic i per SMS.
Solució
Interfície del Producte
from abc import ABC, abstractmethod class Notification(ABC): @abstractmethod def send(self, message: str) -> None: pass
Productes Concrets
class EmailNotification(Notification): def send(self, message: str) -> None: print(f"Sending email with message: {message}") class SMSNotification(Notification): def send(self, message: str) -> None: print(f"Sending SMS with message: {message}")
Creador
class NotificationFactory(ABC): @abstractmethod def create_notification(self) -> Notification: pass def notify(self, message: str) -> None: notification = self.create_notification() notification.send(message)
Creadors Concrets
class EmailNotificationFactory(NotificationFactory): def create_notification(self) -> Notification: return EmailNotification() class SMSNotificationFactory(NotificationFactory): def create_notification(self) -> Notification: return SMSNotification()
Client
def client_code(factory: NotificationFactory, message: str) -> None: factory.notify(message) if __name__ == "__main__": print("App: Launched with the EmailNotificationFactory.") client_code(EmailNotificationFactory(), "Hello via Email!") print("\nApp: Launched with the SMSNotificationFactory.") client_code(SMSNotificationFactory(), "Hello via SMS!")
Explicació del Codi
- Interfície del Producte:
Notification
és una classe abstracta que defineix el mètodesend
. - Productes Concrets:
EmailNotification
iSMSNotification
són implementacions concretes deNotification
. - Creador:
NotificationFactory
és una classe abstracta que declara el mètode de fàbricacreate_notification
i un altre mètodenotify
que utilitza el producte creat. - Creadors Concrets:
EmailNotificationFactory
iSMSNotificationFactory
implementen el mètode de fàbrica per crear instàncies deEmailNotification
iSMSNotification
, respectivament. - Client: El client utilitza el creador concret per enviar notificacions.
Resum
El patró Factory Method és una tècnica poderosa per encapsular la creació d'objectes, proporcionant flexibilitat i reduint la dependència entre classes. En aquest tema, hem vist la seva estructura, un exemple pràctic i un exercici per reforçar els conceptes apresos. Amb aquest patró, podem crear sistemes més modulars i fàcils de mantenir.
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