Heim > Java > javaLernprogramm > Hauptteil

SOLIDE Prinzipien

Linda Hamilton
Freigeben: 2024-10-21 06:12:02
Original
892 Leute haben es durchsucht

SOLID Principles

SOLID ist eine Sammlung grundlegender Prinzipien, die darauf abzielen, die Verwaltbarkeit und Skalierbarkeit von Code in der objektorientierten Programmierung (OOP) zu verbessern. Es besteht aus fünf Grundprinzipien:

  1. S Einzelverantwortungsprinzip  –  SRP
  2. O Stift-geschlossenes Prinzip  –  OCP
  3. L iskovs Substitutionsprinzip  –  LSP
  4. I Prinzip der Schnittstellentrennung  –  ISP
  5. D Abhängigkeitsinversionsprinzip  –  DIP

Diese Prinzipien wurden Anfang der 2000er Jahre von Robert C. Martin (auch bekannt als Uncle Bob) eingeführt und haben seitdem in der Softwareentwicklungsgemeinschaft breite Anwendung gefunden. Durch die Befolgung der SOLID-Prinzipien können Entwickler Code erstellen, der leichter zu verstehen, zu ändern und zu erweitern ist, was zu robusteren und wartbareren Softwaresystemen führt.

Prinzip der Einzelverantwortung (SRP)

Das Prinzip der Einzelverantwortung ist das erste und grundlegendste Prinzip in OOP und SOLID. Wie der Name schon sagt, bedeutet dieses Prinzip „Eine Klasse sollte nur eine bestimmte Verantwortung haben, um die sie sich kümmern muss“.

Angenommen, wir haben eine Klasse namens Invoice, die zwei Methoden genericInvoice() und saveToFiles() enthält.

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Dies ist keine gute Vorgehensweise, da die Rechnungsklasse zwei Verantwortlichkeiten hat. Ein besserer Ansatz wäre, diese Funktionalitäten in dedizierte Klassen zu unterteilen.

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Hier können wir sehen, dass wir zwei Klassen für den Anwendungsfall haben:

  • Rechnung erstellen
  • Speichern Sie es in Dateien

Vorteile der Einhaltung von SRP

  • Verbesserte Code-Organisation: Durch die Aufteilung von Bedenken in verschiedene Klassen wird die Codebasis besser organisiert und einfacher zu navigieren.
  • Bessere Wartbarkeit: Wenn eine Klasse eine einzige Verantwortung hat, ist es einfacher, ihren Zweck zu verstehen und Änderungen ohne unbeabsichtigte Nebenwirkungen vorzunehmen.
  • Erhöhte Wiederverwendbarkeit: Klassen mit einer einzigen Verantwortung sind eher in verschiedenen Teilen der Anwendung oder sogar in anderen Projekten wiederverwendbar.
  • Einfacheres Testen: Klassen mit einer einzigen Verantwortung sind in der Regel kleiner und fokussierter, sodass sie einfacher isoliert getestet werden können.

Open-Closed-Prinzip (OCP)

Das Open-Closed-Prinzip ist ein weiteres Kernprinzip von SOLID. Dieses Prinzip wurde 1997 von Bertrand Meyer eingeführt. Die Idee hinter diesem Prinzip lautet: „Softwareartefakte (Klassen, Module und Funktionen) sollten für Erweiterungen geöffnet, für Änderungen jedoch geschlossen sein.“

Zum Beispiel;

Nehmen wir an, wir haben eine Klasse namens Shape. Mit dieser Klasse können wir die Fläche der Form berechnen.

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Im obigen Code erfordert das Hinzufügen einer neuen Form eine Änderung der vorhandenen Shape-Klasse, was nicht als bewährte Vorgehensweise gilt.

Unten finden Sie ein Codebeispiel, das zeigt, wie das Open-Closed-Prinzip auf dieses Szenario angewendet wird.

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Mit der Anwendung von OCP können wir beliebig viele Formen hinzufügen, ohne die aktuelle Implementierung zu ändern.

HINWEIS: Die Verwendung von Schnittstellen ist nicht die einzige Möglichkeit, OCP zu erreichen.

Vorteile der Befolgung von OCP

  • Reduziertes Fehlerrisiko: Indem vorhandener Code nicht geändert wird, wird das Risiko der Einführung neuer Fehler oder der Beeinträchtigung vorhandener Funktionen minimiert.
  • Verbesserte Wartbarkeit: Code, der dem OCP folgt, ist einfacher zu warten und zu erweitern, da neue Funktionen hinzugefügt werden können, ohne die vorhandene Codebasis zu ändern.
  • Erhöhte Flexibilität: Die Verwendung von Abstraktionen und Polymorphismus ermöglicht flexiblere und anpassungsfähigere Designs und erleichtert so die Anpassung an sich ändernde Anforderungen.

Liskovs Substitutionsprinzip (LSP)

Liskovs Substitutionsprinzip ist ein weiteres wichtiges Prinzip in OOP. Es wurde 1987 von Barbara Liskov während eines Konferenzvortrags über Datenabstraktion vorgestellt.

Das Prinzip besagt: „Objekte einer Oberklasse sollten durch Objekte ihrer Unterklassen ersetzbar sein, ohne die Korrektheit des Programms zu verändern.“

Wenn beispielsweise Kreis und Rechteck Untertypen von Form sind, sollten wir in der Lage sein, das Formobjekt ohne Probleme durch ein Kreis- oder Rechteckobjekt zu ersetzen.

public class Shape {
    private String shapeType;
    private double radius;
    private double length;
    private double width;

    public Shape(String shapeType, double radius, double length, double width) {
        this.shapeType = shapeType;
        this.radius = radius;
        this.length = length;
        this.width = width;
    }

    public double area() {
        if (shapeType.equals("circle")) {
            return Math.PI * (radius * radius);
        } else if (shapeType.equals("rectangle")) {
            return length * width;
        } else {
            throw new IllegalArgumentException("Unknown shape type");
        }
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Shape circle = new Shape("circle", 5, 0, 0);
        Shape rectangle = new Shape("rectangle", 0, 4, 6);

        System.out.println(circle.area());
        System.out.println(rectangle.area());
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Wie in diesem Beispiel gezeigt, bedeutet die Einhaltung des Liskov-Substitutionsprinzips, dass wir in der Lage sein sollten, eine Superklasseninstanz nahtlos durch eine Unterklasseninstanz zu ersetzen.

Vorteile der Befolgung von LSP

  • Verbesserte Code-Wiederverwendbarkeit: Indem sichergestellt wird, dass Subtypen ihre Basistypen ersetzen können, kann Code, der den Basistyp verwendet, auch mit jedem seiner Subtypen funktionieren, was die Wiederverwendung von Code fördert.
  • Verbesserte Wartbarkeit: Code, der LSP folgt, ist einfacher zu warten, da er das Risiko der Einführung von Fehlern beim Ändern oder Erweitern der Codebasis verringert.
  • Bessere Testbarkeit: LSP erleichtert das Schreiben von Komponententests für Klassen und ihre Untertypen, da die Tests gegen den Basistyp geschrieben werden können und für alle Untertypen funktionieren sollten.

Prinzip der Schnittstellentrennung (ISP)

Das Interface-Segregationsprinzip ist eines der fünf SOLID-Prinzipien, die von Robert C. Martin eingeführt wurden. Darin heißt es: „Clients sollten nicht gezwungen werden, sich auf Schnittstellen zu verlassen, die sie nicht nutzen.“

Mit anderen Worten: Die Verwendung vieler aufgabenspezifischer Schnittstellen ist besser als die Verwendung einer Allzweckschnittstelle.

Das folgende Beispiel zeigt die Verwendung einer Allzweckschnittstelle.

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die Verwendung einer Allzweckschnittstelle wie Multifunktionsdrucker zwingt uns dazu, unnötige Methoden zu implementieren, was als schlechte Praxis angesehen wird. Lassen Sie uns untersuchen, wie wir das Prinzip der Schnittstellentrennung auf dieses Szenario anwenden können.

Schnittstellen

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Implementierungen

public class Shape {
    private String shapeType;
    private double radius;
    private double length;
    private double width;

    public Shape(String shapeType, double radius, double length, double width) {
        this.shapeType = shapeType;
        this.radius = radius;
        this.length = length;
        this.width = width;
    }

    public double area() {
        if (shapeType.equals("circle")) {
            return Math.PI * (radius * radius);
        } else if (shapeType.equals("rectangle")) {
            return length * width;
        } else {
            throw new IllegalArgumentException("Unknown shape type");
        }
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Shape circle = new Shape("circle", 5, 0, 0);
        Shape rectangle = new Shape("rectangle", 0, 4, 6);

        System.out.println(circle.area());
        System.out.println(rectangle.area());
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Durch die Anwendung des ISP teilen wir ihn in kleinere, rollenspezifische Schnittstellen auf – wie Drucker, Scanner und Fax. Dadurch kann jede Klasse (z. B. BasicPrinter, AdvancedPrinter oder FaxMachine) nur die relevante Funktionalität implementieren, wodurch die Modularität gefördert und unnötige Abhängigkeiten reduziert werden.

Vorteile, wenn Sie einem ISP folgen

  • Modularer und wiederverwendbarer Code: Durch die Aufteilung großer Schnittstellen in kleinere, spezifischere Schnittstellen wird der Code modularer und wiederverwendbarer. Klassen oder Module können nur die Schnittstellen implementieren, die sie benötigen, wodurch unnötige Abhängigkeiten reduziert werden und die Wiederverwendung von Code in verschiedenen Teilen des Systems einfacher wird.
  • Reduzierte Codekomplexität: Wenn Klassen oder Module nur von den Schnittstellen abhängen, die sie benötigen, wird der Code weniger komplex und leichter zu verstehen. Dies liegt daran, dass sich Entwickler nicht mit unnötigen Methoden oder Abhängigkeiten auseinandersetzen müssen. Diese sind für ihren spezifischen Anwendungsfall nicht relevant.
  • Verbesserte Wartbarkeit: Mit kleineren und fokussierteren Schnittstellen wird es einfacher, den Code zu warten. Änderungen an einer Schnittstelle wirken sich weniger wahrscheinlich auf andere Teile des Systems aus, wodurch das Risiko der Einführung von Fehlern oder der Beeinträchtigung vorhandener Funktionen verringert wird.
  • Bessere Testbarkeit: Kleinere und fokussiertere Schnittstellen erleichtern das Schreiben von Komponententests für einzelne Komponenten. Dies liegt daran, dass sich die Tests auf bestimmte Verhaltensweisen konzentrieren können, ohne durch irrelevante Methoden oder Abhängigkeiten beeinträchtigt zu werden.
  • Erhöhte Flexibilität: Durch die Bindung an den ISP wird das System flexibler und lässt sich einfacher erweitern oder ändern. Neue Funktionen oder Anforderungen können hinzugefügt werden, indem neue Schnittstellen erstellt oder bestehende geändert werden, ohne dass sich dies auf das gesamte System auswirkt.

Abhängigkeitsinversionsprinzip (DIP)

Das Abhängigkeitsinversionsprinzip ist das letzte Prinzip von SOLID. Was auch von Robert C. Martin eingeführt wurde. Dies fördert lose gekoppelten Code.

DIP gibt einige Punkte an:

  • High-Level-Module sollten nicht von Low-Level-Modulen abhängen.
  • Beide sollten von der Abstraktion abhängen.
  • Abstraktion sollte nicht von Details abhängen.
  • Details sollten von der Abstraktion abhängen.

Einfach ausgedrückt sollte eine Klasse nicht direkt von anderen spezifischen Klassen (konkreten Implementierungen) abhängig sein, sondern von Schnittstellen oder abstrakten Klassen. Dadurch wird der Code flexibler und einfacher zu warten, da Sie Implementierungen austauschen können, ohne die abhängige Klasse zu ändern.

Eng gekoppelter Code (ohne DIP)

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wie im obigen Beispiel gezeigt, hängt die Computerklasse direkt von der Tastaturklasse ab.

Lose gekoppelter Code (mit DIP)

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Jetzt ist der Computer auf die InputDevice-Schnittstelle angewiesen, nicht auf eine bestimmte Tastatur. Dies erleichtert den Wechsel zu einem anderen Eingabegerät, beispielsweise einer drahtlosen Tastatur, ohne die Computerklasse zu ändern.

Vorteile der Befolgung von DIP

  • Lose Kopplung: Durch die Abhängigkeit von Abstraktionen statt von konkreten Implementierungen wird der Code weniger eng gekoppelt, wodurch es einfacher wird, einen Teil des Systems zu ändern, ohne andere zu beeinflussen.
  • Verbesserte Wartbarkeit: Änderungen an Low-Level-Modulen wirken sich nicht auf High-Level-Module aus, wodurch das System einfacher zu warten und zu erweitern ist.
  • Verbesserte Testbarkeit: High-Level-Module können mithilfe von Scheinimplementierungen der Low-Level-Module getestet werden, wodurch das Testen schneller und zuverlässiger wird.
  • Erhöhte Wiederverwendbarkeit: High-Level-Module können in verschiedenen Kontexten wiederverwendet werden, ohne dass die Low-Level-Module, von denen sie abhängen, geändert werden müssen.

Abschluss

Zusammenfassend lässt sich sagen, dass die SOLID-Prinzipien: Single Responsibility, Open-Closed, Liskov-Substitution, Interface Segregation und Dependency Inversion wesentliche Richtlinien für das Schreiben von sauberem, wartbarem und skalierbarem Code in der objektorientierten Programmierung bieten.

Durch die Einhaltung dieser Prinzipien können Entwickler Systeme erstellen, die einfacher zu verstehen, zu ändern und zu erweitern sind, was letztendlich zu qualitativ hochwertigerer Software und effizienteren Entwicklungsprozessen führt.

Zusammenfassung

Vielen Dank für das Lesen dieses Artikels! Ich hoffe, Sie haben jetzt ein solides Verständnis der SOLID-Prinzipien und wie Sie sie anwenden können, um Ihre Projekte zu verbessern.

Folgen Sie mir auf:
  • LinkedIn — @nsadisha
  • GitHub — @nsadisha
  • Mittel — @nsadisha
  • Dev.to — @nsadisha

— Sadisha Nimsara

Das obige ist der detaillierte Inhalt vonSOLIDE Prinzipien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!