Modèles de conception avancés en Java : de la théorie aux exemples complexes
Les modèles de conception sont des solutions éprouvées aux problèmes typiques rencontrés lors du développement de logiciels. Si les modèles de base (Singleton, Factory, Observer) sont familiers à la plupart des développeurs Java, les modèles avancés nécessitent une compréhension approfondie de l'architecture et la capacité de les appliquer dans des scénarios métier complexes. Dans cet article, nous analyserons trois modèles puissants : Visitor, Command et State — avec des exemples concrets en Java qui vous aideront à écrire un code plus flexible et maintenable.
1. Modèle Visitor : séparation des algorithmes de la structure des données
Objectif : Permet d'ajouter de nouvelles opérations pour des objets de différentes classes sans modifier les classes elles-mêmes. Idéal pour travailler avec des hiérarchies complexes où différentes actions doivent être effectuées en fonction du type d'objet.
Problème : Imaginez un système de gestion documentaire avec des classes TextDocument, ImageDocument et SpreadsheetDocument. Vous devez implémenter l'exportation en PDF, HTML et TXT. Sans Visitor, chaque nouveau format d'exportation nécessiterait de modifier toutes les classes de documents.
Solution avec Visitor :
// 1. Interface de l'élément (document)interface DocumentElement { void accept(DocumentVisitor visitor);}
// 2. Éléments concretsclass TextDocument implements DocumentElement { private String content; public TextDocument(String content) { this.content = content; } public String getContent() { return content; } @Override public void accept(DocumentVisitor visitor) { visitor.visit(this); }}
class ImageDocument implements DocumentElement { private byte[] imageData; public ImageDocument(byte[] data) { this.imageData = data; } public byte[] getImageData() { return imageData; } @Override public void accept(DocumentVisitor visitor) { visitor.visit(this); }}
// 3. Interface du visiteurinterface DocumentVisitor { void visit(TextDocument doc); void visit(ImageDocument doc); void visit(SpreadsheetDocument doc);}
// 4. Visiteur concret — exportation en HTMLclass HtmlExporter implements DocumentVisitor { private StringBuilder sb = new StringBuilder(); @Override public void visit(TextDocument doc) { sb.append("<html><body><p>") .append(doc.getContent()) .append("</p></body></html>"); } @Override public void visit(ImageDocument doc) { sb.append("<html><body><img src='data:image/png;base64,") .append(Base64.getEncoder().encodeToString(doc.getImageData())) .append("'/></body></html>"); } @Override public void visit(SpreadsheetDocument doc) { sb.append("<html><body><table>...</table></body></html>"); } public String getResult() { return sb.toString(); }}
// 5. Code clientpublic class DocumentSystem { public static void main(String[] args) { List<DocumentElement> documents = Arrays.asList( new TextDocument("Hello World"), new ImageDocument(new byte[]{1,2,3}) ); HtmlExporter exporter = new HtmlExporter(); for (DocumentElement doc : documents) { doc.accept(exporter); } System.out.println(exporter.getResult()); }}Avantage clé : Pour ajouter un nouveau format (par exemple, JSON), il suffit de créer une nouvelle classe JsonExporter implements DocumentVisitor — aucune des classes de documents n'est modifiée.