SOLID-Prinzipien in Java: Theorie und fortgeschrittene Praxis

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

SOLID-Prinzipien in Java: Von der Theorie zur fortgeschrittenen Praxis



Die SOLID-Prinzipien sind das Fundament des objektorientierten Designs, das Entwicklern hilft, Code zu erstellen, der änderungsresistent, leicht testbar und skalierbar ist. Für einen Java-Entwickler bedeutet das Verständnis dieser Prinzipien auf fortgeschrittenem Niveau nicht nur die Kenntnis der Definitionen, sondern die Fähigkeit, ihre Verletzung in Legacy-Code zu erkennen und Muster für das Refactoring anzuwenden. In diesem Artikel werden wir jedes Prinzip mit Schwerpunkt auf komplexe, aber typische Situationen analysieren.



1. Single Responsibility Principle (SRP): Die Grenze zwischen Verantwortung und Kohäsion



Theorie: Eine Klasse sollte nur einen Grund für Änderungen haben. In der Praxis bedeutet dies, dass eine Klasse für einen Teil der Funktionalität des Programms verantwortlich sein sollte.



Fortgeschrittene Praxis: Oft zeigt sich eine SRP-Verletzung nicht in einer offensichtlichen Vermischung von Logik, sondern in einer "verschwommenen" Verantwortung. Betrachten wir ein Beispiel einer Klasse für die Arbeit mit Berichten:



// SRP-Verletzung: Die Klasse kümmert sich um Daten, Formatierung und Versandpublic class ReportService {    public void generateReport(List<Data> data) {        // Berechnungslogik        Map<String, Integer> aggregated = aggregate(data);        // Formatierung (HTML)        String html = formatToHtml(aggregated);        // Versand per E-Mail        sendEmail(html, "admin@example.com");    }

private Map<String, Integer> aggregate(List<Data> data) { // ... return new HashMap<>(); }

private String formatToHtml(Map<String, Integer> data) { // ... return "<html>...</html>"; }

private void sendEmail(String content, String to) { // ... }}


Problem: Wenn sich das Berichtsformat ändert (PDF statt HTML), muss diese Klasse geändert werden. Wenn sich die Versandart ändert (Telegram statt E-Mail) – ebenfalls. Lösung: Aufteilung in drei Klassen:



public class ReportAggregator {    public Map<String, Integer> aggregate(List<Data> data) { ... }}

public class HtmlReportFormatter { public String format(Map<String, Integer> data) { ... }}

public class EmailSender { public void send(String content, String to) { ... }}

// Komposition im Servicepublic class ReportGenerationFacade { private ReportAggregator aggregator; private HtmlReportFormatter formatter; private EmailSender sender;

public void generateAndSend(List<Data> data) { var aggregated = aggregator.aggregate(data); var html = formatter.format(aggregated); sender.send(html, "admin@example.com"); }}


2. Open-Closed Principle (OCP): Die Kunst der Erweiterung durch Abstraktionen



Theorie: Klassen sollten für Erweiterungen offen, aber für Modifikationen geschlossen sein.



Fortgeschrittene Praxis: Eine typische Verletzung sind if-else- oder switch-Ketten für verschiedene Objekttypen. Die fortgeschrittene Methode ist die Verwendung von Strategie oder Template Method mit Polymorphismus.



// OCP-Verletzung: Beim Hinzufügen eines neuen Zahlungstyps muss die Klasse geändert werdenpublic class PaymentProcessor {    public void processPayment(String type, double amount) {        if ("CREDIT_CARD".equals(type)) {            // Logik für Kreditkarte        } else if ("PAYPAL".equals(type)) {            // Logik für PayPal        } else if ("BITCOIN".equals(type)) {            // Logik für Bitcoin        }    }}


Korrektur über Interface und Factory:



public interface PaymentMethod {    void pay(double amount);}

public class CreditCardPayment implements PaymentMethod { public void pay(double amount) { ... }}

public class PayPalPayment implements PaymentMethod

Blogs

Buchempfehlungen