Le Pattern Simple Factory
Le pattern Simple Factory centralise la logique d'instanciation des objets dans une classe unique. Bien qu'il ne fasse pas officiellement partie des 23 patterns du GoF (Gang of Four), il est largement utilisé pour découpler le client des classes concrètes. Pour illustrer ce concept, modélisons un système de traitement de paiements.
package com.architecture.creational.simplefactory;
public abstract class PaymentGateway {
protected double transactionAmount;
public void setAmount(double amount) {
this.transactionAmount = amount;
}
public abstract boolean executeTransaction();
}
package com.architecture.creational.simplefactory;
public class CreditCardGateway extends PaymentGateway {
@Override
public boolean executeTransaction() {
System.out.println("Traitement du paiement par carte de crédit : " + transactionAmount + " €");
return true;
}
}
package com.architecture.creational.simplefactory;
public class PayPalGateway extends PaymentGateway {
@Override
public boolean executeTransaction() {
System.out.println("Traitement du paiement via PayPal : " + transactionAmount + " €");
return true;
}
}
package com.architecture.creational.simplefactory;
public class BankTransferGateway extends PaymentGateway {
@Override
public boolean executeTransaction() {
if (transactionAmount <= 0) {
System.out.println("Montant invalide pour un virement bancaire.");
return false;
}
System.out.println("Traitement du virement bancaire : " + transactionAmount + " €");
return true;
}
}
La classe fabrique évalue le paramètre fourni pour retourner l'implémentation appropriée :
package com.architecture.creational.simplefactory;
public class PaymentGatewayFactory {
public static PaymentGateway buildGateway(String method) {
switch (method.toLowerCase()) {
case "credit_card":
return new CreditCardGateway();
case "paypal":
return new PayPalGateway();
case "bank_transfer":
return new BankTransferGateway();
default:
throw new IllegalArgumentException("Méthode de paiement non supportée : " + method);
}
}
}
Le client n'a plus qu'à interagir avec l'interface abstraite, sans se soucier de l'instanciation :
package com.architecture.creational.simplefactory;
public class CheckoutService {
public static void main(String[] args) {
PaymentGateway gateway = PaymentGatewayFactory.buildGateway("paypal");
gateway.setAmount(150.75);
gateway.executeTransaction();
}
}
Le Pattern Factory Method
Le pattern Factory Method (Méthode de Fabrique) pousse le découplage plus loin en définissant une interface pour la création d'objets, tout en laissant les sous-classes décider quelle clasce instancier. Cela élimine la nécessité de modifier une classe fabrique centrale lors de l'ajout de nouveaux types.
package com.architecture.creational.factorymethod;
public interface GatewayFactoryMethod {
PaymentGateway instantiateGateway();
}
package com.architecture.creational.factorymethod;
public class CreditCardFactory implements GatewayFactoryMethod {
@Override
public PaymentGateway instantiateGateway() {
return new CreditCardGateway();
}
}
package com.architecture.creational.factorymethod;
public class PayPalFactory implements GatewayFactoryMethod {
@Override
public PaymentGateway instantiateGateway() {
return new PayPalGateway();
}
}
package com.architecture.creational.factorymethod;
public class BankTransferFactory implements GatewayFactoryMethod {
@Override
public PaymentGateway instantiateGateway() {
return new BankTransferGateway();
}
}
L'instanciation est désormais déléguée à la fabrique concrète correspondante :
package com.architecture.creational.factorymethod;
public class CheckoutService {
public static void main(String[] args) {
GatewayFactoryMethod factory = new PayPalFactory();
PaymentGateway gateway = factory.instantiateGateway();
gateway.setAmount(150.75);
gateway.executeTransaction();
}
}
Analyse Comparative
Le Simple Factory offre l'avantage de regrouper la logique de création, supprimant ainsi la dépendance du client envers les produits concrets. Cependant, il viole le principe Ouvert/Fermé (Open-Closed Principle) : l'ajout d'un nouveau moyen de paiement nécessite la modification directe de la méthode de la fabrique (ajout d'un nouveau cas dans le bloc switch).
À l'inverse, le Factory Method respecte strictement le principe Ouvert/Fermé. L'architecture est ouverte à l'extension (ajout d'une nouvelle fabrique concrète et d'un nouveau produit) mais fermée à la modification (aucune classe existante n'a besoin d'être altérée pour supporter le nouveau comportement).