Le Design Pattern Abstract Factory - un exemple concret et simple pour tous
Le Design Pattern Abstract Factory : un exemple concret et simple pour tous
Lorsqu’on développe un logiciel, on se retrouve souvent à devoir créer plusieurs objets liés entre eux. Et parfois, ces objets doivent exister en plusieurs “versions” différentes, tout en restant compatibles entre eux. Le design pattern Abstract Factory est fait pour ça.
Dans cet article, je t’explique un cas réel, simple et fluide, compréhensible aussi bien par un débutant que par un développeur confirmé.
🎮 Cas réel : La création d’un jeu vidéo multi‑univers
Imaginons que tu es en train de créer un jeu vidéo pour ton site ou ton application. Dans ce jeu, le joueur peut choisir parmi deux univers différents :
- 🌲 L’univers Médiéval (chevaliers, épées, dragons…)
- 🤖 L’univers Futuriste (robots, lasers, drones…)
Quel que soit l’univers choisi, ton jeu a besoin de créer deux types d’objets :
- Un personnage (Héros médiéval ou Robot combattant)
- Une arme (Épée ou Laser)
Le problème :
Si tu écris ton code naïvement, tu vas te retrouver à multiplier les conditions :
if (univers == "medieval") { ... }
else if (univers == "futuriste") { ... }
Et cela un peu partout dans ton code. C’est long, fragile, et difficile à maintenir.
🎯 L’objectif : créer le bon “package” d’objets selon l’univers
Quand le joueur choisit l’univers Médiéval, il faut :
- un héro médiéval
- une épée
Quand le joueur choisit Futuriste, il faut :
- un robot
- un laser
Et tout ça automatiquement, sans écrire dix mille conditions.
🏭 La solution : l’Abstract Factory
L’Abstract Factory va jouer le rôle d’une usine à objets.
- Une usine Médiévale fabrique uniquement des objets médiévaux.
- Une usine Futuriste fabrique uniquement des objets futuristes.
Le jeu ne se préoccupe plus de comment les objets sont fabriqués. Il demande simplement :
“Usine, donne‑moi un héros et une arme !”
Et l’usine renvoie la bonne version.
🧩 Pourquoi c’est utile dans la vraie vie ?
Ce pattern est utilisé dans énormément de domaines :
- Apps multi‑thèmes (clair/sombre) → chaque thème a ses couleurs, icônes, polices.
- Applications multi‑plateformes → Windows, Mac, Linux ont leurs propres composants.
- Systèmes de paiement → chaque prestataire (Stripe, PayPal…) a ses objets à lui.
- Jeux vidéo → comme notre exemple, pour gérer plusieurs mondes sans complexité.
Il permet :
- une organisation propre,
- une extension facile,
- zéro changement dans le reste du code quand on ajoute un nouvel univers.
🧠 Résumé simple pour tous
Imagine que tu veux toujours un “pack” cohérent :
- pack médiéval
- pack futuriste
L’Abstract Factory est simplement :
Une usine qui te garantit que tous les objets fabriqués ensemble appartiennent au même univers.
Sans mélange. Sans erreur. Et sans gros if/else partout.
🧪 Exemple complet en Java (code intégré)
Voici un exemple complet en Java du cas réel présenté plus haut. Il permet d’illustrer clairement comment fonctionne l’Abstract Factory dans un jeu vidéo multi-univers.
1. Interfaces de base (produits)
interface Personnage {
void attaquer();
}
interface Arme {
void utiliser();
}
2. Implémentations concrètes (Médiéval & Futuriste)
class HeroMedieval implements Personnage {
@Override
public void attaquer() {
System.out.println("Le héros médiéval attaque avec courage !");
}
}
class Epee implements Arme {
@Override
public void utiliser() {
System.out.println("L'épée tranche l'air !");
}
}
class RobotFuturiste implements Personnage {
@Override
public void attaquer() {
System.out.println("Le robot futuriste lance une attaque numérique !");
}
}
class Laser implements Arme {
@Override
public void utiliser() {
System.out.println("Le laser tire une rafale lumineuse !");
}
}
3. Abstract Factory
interface UniversFactory {
Personnage creerPersonnage();
Arme creerArme();
}
4. Factories concrètes
class MedievalFactory implements UniversFactory {
@Override
public Personnage creerPersonnage() {
return new HeroMedieval();
}
@Override
public Arme creerArme() {
return new Epee();
}
}
class FuturisteFactory implements UniversFactory {
@Override
public Personnage creerPersonnage() {
return new RobotFuturiste();
}
@Override
public Arme creerArme() {
return new Laser();
}
}
5. Classe Jeu
class Jeu {
private final Personnage personnage;
private final Arme arme;
public Jeu(UniversFactory factory) {
this.personnage = factory.creerPersonnage();
this.arme = factory.creerArme();
}
public void jouer() {
personnage.attaquer();
arme.utiliser();
}
}
6. Main
public class Main {
public static void main(String[] args) {
System.out.println("=== Univers Médiéval ===");
UniversFactory medieval = new MedievalFactory();
Jeu jeuMedieval = new Jeu(medieval);
jeuMedieval.jouer();
System.out.println("
=== Univers Futuriste ===");
UniversFactory futuriste = new FuturisteFactory();
Jeu jeuFuturiste = new Jeu(futuriste);
jeuFuturiste.jouer();
}
}
Résultat
=== Univers Médiéval ===
Le héros médiéval attaque avec courage !
L'épée tranche l'air !
=== Univers Futuriste ===
Le robot futuriste lance une attaque numérique !
Le laser tire une rafale lumineuse !
📝 Conclusion
L’Abstract Factory n’est pas compliqué : c’est juste une façon propre de créer plusieurs familles d’objets compatibles entre eux. Que tu sois jeune développeur, étudiant, passionné de jeux vidéo ou ingénieur confirmé, ce pattern te permet d’éviter le code fouillis et de rendre ton application plus claire, plus évolutive, plus robuste.