Fortgeschrittene Entwurfsmuster in Java: Von der Theorie zu komplexen Beispielen
Entwurfsmuster sind bewährte Lösungen für typische Probleme, die bei der Softwareentwicklung auftreten. Während grundlegende Muster (Singleton, Factory, Observer) den meisten Java-Entwicklern bekannt sind, erfordern fortgeschrittene Muster ein tiefes Verständnis der Architektur und die Fähigkeit, sie in komplexen Geschäftsszenarien anzuwenden. In diesem Artikel analysieren wir drei leistungsstarke Muster: Visitor, Command und State — mit realen Beispielen in Java, die Ihnen helfen, flexibleren und wartbareren Code zu schreiben.
1. Visitor-Muster: Trennung von Algorithmen und Datenstruktur
Zweck: Ermöglicht das Hinzufügen neuer Operationen für Objekte verschiedener Klassen, ohne die Klassen selbst zu ändern. Ideal für die Arbeit mit komplexen Hierarchien, bei denen je nach Objekttyp unterschiedliche Aktionen ausgeführt werden müssen.
Problem: Stellen Sie sich ein Dokumentenverwaltungssystem vor, mit den Klassen TextDocument, ImageDocument und SpreadsheetDocument. Sie müssen den Export in PDF, HTML und TXT implementieren. Ohne Visitor würde jedes neue Exportformat Änderungen an allen Dokumentklassen erfordern.
Lösung mit Visitor:
// 1. Element-Schnittstelle (Dokument)interface DocumentElement { void accept(DocumentVisitor visitor);}
// 2. Konkrete Elementeclass 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. Besucher-Schnittstelleinterface DocumentVisitor { void visit(TextDocument doc); void visit(ImageDocument doc); void visit(SpreadsheetDocument doc);}
// 4. Konkreter Besucher — Export nach 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. Client-Codepublic 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()); }}Wichtigster Vorteil: Um ein neues Format (z.B. JSON) hinzuzufügen, reicht es, eine neue Klasse JsonExporter implements DocumentVisitor zu erstellen — keine der Dokumentklassen wird geändert.