SOLID-Prinzipien in Java: Von der Theorie zur Praxis
\n\nSOLID ist ein Akronym für fünf fundamentale Prinzipien der objektorientierten Programmierung, formuliert von Robert C. Martin (Uncle Bob). Diese Prinzipien helfen dabei, flexiblen, wartbaren und skalierbaren Code zu erstellen. In diesem Artikel analysieren wir jedes Prinzip anhand von Java-Beispielen, zeigen, wie sie verletzt werden, und wie man sie richtig anwendet.
\n\nWozu braucht man die SOLID-Prinzipien?
\nOhne SOLID wird Code schnell zu „Spaghetti-Code“. Kennen Sie die Situation, dass die Änderung einer Klasse drei andere zerstört? Oder dass eine Methode zu viel tut? SOLID löst diese Probleme. Jedes Prinzip ist eine Regel, die Code macht:
\n- \n
- Änderungsresistent — neue Anforderungen zerstören nicht die alte Logik. \n
- Verständlich — jede Klasse ist für eine Sache verantwortlich. \n
- Testbar — einfach Unit-Tests zu schreiben. \n
1. Single Responsibility Principle (SRP) — Prinzip der einzigen Verantwortung
\nFormulierung: „Eine Klasse sollte nur einen Grund zur Änderung haben“.
\nEinfach ausgedrückt: Eine Klasse sollte nur eine Sache tun. Wenn eine Klasse mehr als eine Verantwortung hat, ist sie schwer zu warten.
\n\nVerletzung des SRP (schlechter Code)
\npublic class OrderService {\n public void createOrder(Order order) {\n // Logik zur Auftragserstellung\n saveToDatabase(order);\n sendEmailConfirmation(order);\n }\n\n private void saveToDatabase(Order order) {\n // Speichern in der DB\n }\n\n private void sendEmailConfirmation(Order order) {\n // E-Mail senden\n }\n}\nProblem: Die Klasse ist verantwortlich für die Geschäftslogik, die Datenbankarbeit und das Senden von Benachrichtigungen. Eine Änderung des E-Mail-Dienstes erfordert eine Änderung von OrderService.
Korrekte Implementierung des SRP
\npublic class OrderService {\n private final OrderRepository repository;\n private final EmailService emailService;\n\n public OrderService(OrderRepository repo, EmailService email) {\n this.repository = repo;\n this.emailService = email;\n }\n\n public void createOrder(Order order) {\n repository.save(order);\n emailService.sendConfirmation(order);\n }\n}\n\npublic class OrderRepository {\n public void save(Order order) { /* DB-Logik */ }\n}\n\npublic class EmailService {\n public void sendConfirmation(Order order) { /* E-Mail-Logik */ }\n}\nJetzt hat jede Klasse einen Grund zur Änderung. OrderService ändert sich nur bei Änderung des Geschäftsprozesses zur Auftragserstellung.
2. Open/Closed Principle (OCP) — Prinzip der Offenheit/Geschlossenheit
\nFormulierung: „Klassen sollten offen für Erweiterung, aber geschlossen für Modifikation sein“.
\nDas bedeutet, dass Sie neue Funktionalität durch neuen Code hinzufügen sollten, nicht durch Änderung vorhandenen Codes.
\n\nVerletzung des OCP (schlechter Code)
\npublic class AreaCalculator {\n public double calculateArea(Object shape) {\n if (shape instanceof Rectangle) {\n Rectangle r = (Rectangle) shape;\n return r.width * r.height;\n } else if (shape instanceof Circle) {\n Circle c = (Circle) shape;\n return Math.PI * c.radius * c.radius;\n }\n throw new IllegalArgumentException("Unbekannte Form");\n }\n}\nUm ein Dreieck hinzuzufügen, muss die Methode calculateArea geändert werden — das verletzt das OCP.
Korrekte Implementierung des OCP
\npublic interface Shape {\n double calculateArea();\n}\n\npublic class Rectangle implements Shape {\n private double width, height;\n public Rectangle(double w, double h) { this.width = w; this.height = h; }\n @Override\n public double calculateArea() { return width * height; }\n}\n\npublic class Circle implements Shape {\n private double radius;\n