Patron Fabrique
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 66 sur 87.
Le Factory Pattern est un patron de conception de création qui délègue la création d'objets à une méthode ou une classe séparée. Au lieu d'utiliser new directement dans votre code, vous demandez à une fabrique de créer des objets pour vous. Ceci est particulièrement utile lorsque vous avez plusieurs classes liées qui partagent une interface ou un parent commun.
Considérez un système de notification capable d'envoyer des e-mails, des SMS ou des notifications push. Sans fabrique (factory), votre code devrait connaître chaque classe concrète :
// Sans Factory - le client doit connaître toutes les classes concrètes
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Avec le Factory Pattern, vous centralisez cette logique de création :
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}Désormais, le code client est plus propre et ne dépend pas de classes concrètes :
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Sortie : Email: Hello!L'avantage principal est que l'ajout de nouveaux types de notification nécessite seulement la mise à jour de la fabrique — le code client reste inchangé. Cela suit le principe de la programmation vers une interface, rendant votre système plus flexible et plus facile à étendre.
Défi
FacileConstruisons un système de dessin de formes en utilisant le Factory Pattern ! Au lieu de créer des objets de forme directement dans votre code, vous allez centraliser la logique de création dans une fabrique qui produit différents types de formes basés sur un simple identifiant sous forme de chaîne de caractères.
Vous organiserez votre code sur quatre fichiers :
Shape.java: Définissez une interface appeléeShapequi sert de contrat commun pour toutes les formes. Votre interface doit déclarer une seule méthodedraw()qui ne retourne rien mais affiche des informations sur la forme en cours de dessin.Shapes.java: Créez trois classes qui implémentent votre interfaceShape:Circle- sa méthodedraw()doit afficherDrawing a CircleRectangle- sa méthodedraw()doit afficherDrawing a RectangleTriangle- sa méthodedraw()doit afficherDrawing a TriangleShapeFactory.java: Créez la classe factory qui gère la création des formes. VotreShapeFactorydoit avoir une méthode statiquecreateShape(String type)qui retourne uneShape. En fonction du paramètre type :- Si type est égal à
"circle", retournez un nouveauCircle - Si type est égal à
"rectangle", retournez un nouveauRectangle - Si type est égal à
"triangle", retournez un nouveauTriangle - Pour toute autre valeur, retournez
null
- Si type est égal à
Main.java: Rassemblez votre système de fabrique ! Vous recevrez deux entrées : deux types de formes (tous deux des Strings).Pour chaque entrée, utilisez votre
ShapeFactorypour créer la forme et stockez-la dans une variableShape. Si la fabrique retourne une forme valide (non nulle), appelez sa méthodedraw(). Si elle retourne nulle, affichezUnknown shape: [type]où [type] est l'entrée qui a été fournie.Traitez les deux entrées dans l'ordre, chacune sur sa propre ligne de sortie.
Vous recevrez deux entrées dans l'ordre : le premier type de forme (String) et le second type de forme (String).
Remarquez comment votre classe Main n'utilise jamais new Circle() ou new Rectangle() directement — elle ne connaît que l'interface Shape et demande à la fabrique de créer des objets. C'est toute la puissance du Factory Pattern : le code client est découplé des classes concrètes !
Aide-mémoire
Le Factory Pattern (ou patron de méthode de fabrique) est un patron de conception de création qui délègue la création d'objets à une méthode ou une classe distincte, centralisant la logique de création et découplant le code client des implémentations concrètes.
Au lieu d'instancier des objets directement avec new, vous utilisez une méthode de fabrique :
// Sans Factory - le client dépend des classes concrètes
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Avec le Factory Pattern, définissez une interface commune et des implémentations concrètes :
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}Créez une classe de fabrique avec une méthode de création statique :
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}Le code client utilise la fabrique au lieu de l'instanciation directe :
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Résultat : Email: Hello!Avantages : L'ajout de nouveaux types nécessite uniquement la mise à jour de la fabrique — le code client reste inchangé. Cela suit le principe de programmation vers une interface, rendant les systèmes plus flexibles et plus faciles à étendre.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire deux types de formes
String type1 = scanner.nextLine();
String type2 = scanner.nextLine();
// TODO: Utiliser ShapeFactory pour créer la première forme
// Si la forme n'est pas null, appeler draw()
// Si la forme est null, afficher "Unknown shape: [type]"
// TODO: Faire la même chose pour la deuxième forme
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur