Offenes / geschlossenes Prinzip in Java

1. Übersicht

In diesem Tutorial werden wir das Open / Closed-Prinzip (OCP) als eines der SOLID-Prinzipien der objektorientierten Programmierung diskutieren.

Insgesamt werden wir detailliert darauf eingehen, was dieses Prinzip ist und wie es beim Entwurf unserer Software implementiert wird.

2. Offenes / geschlossenes Prinzip

Wie der Name schon sagt, besagt dieses Prinzip, dass Software-Entitäten zur Erweiterung geöffnet, aber zur Änderung geschlossen sein sollten. Wenn sich die Geschäftsanforderungen ändern, kann die Entität daher erweitert, aber nicht geändert werden.

In der folgenden Abbildung konzentrieren wir uns darauf, wie Schnittstellen eine Möglichkeit sind, OCP zu folgen.

2.1. Nicht konform

Nehmen wir an, wir erstellen eine Taschenrechner-App, die möglicherweise mehrere Operationen wie Addition und Subtraktion enthält.

Zunächst definieren wir eine Schnittstelle der obersten Ebene - CalculatorOperation :

public interface CalculatorOperation {}

Definieren wir eine Additionsklasse , die zwei Zahlen addiert und die C alculatorOperation implementiert :

public class Addition implements CalculatorOperation { private double left; private double right; private double result = 0.0; public Addition(double left, double right) { this.left = left; this.right = right; } // getters and setters }

Ab sofort haben wir nur eine Klassenaddition , daher müssen wir eine andere Klasse mit dem Namen Subtraktion definieren :

public class Subtraction implements CalculatorOperation { private double left; private double right; private double result = 0.0; public Subtraction(double left, double right) { this.left = left; this.right = right; } // getters and setters }

Definieren wir nun unsere Hauptklasse, die unsere Taschenrechneroperationen ausführt:

public class Calculator { public void calculate(CalculatorOperation operation) { if (operation == null) { throw new InvalidParameterException("Can not perform operation"); } if (operation instanceof Addition) { Addition addition = (Addition) operation; addition.setResult(addition.getLeft() + addition.getRight()); } else if (operation instanceof Subtraction) { Subtraction subtraction = (Subtraction) operation; subtraction.setResult(subtraction.getLeft() - subtraction.getRight()); } } }

Obwohl dies in Ordnung zu sein scheint, ist es kein gutes Beispiel für die OCP. Wenn eine neue Anforderung zum Hinzufügen von Multiplikations- oder Divisionsfunktionen eingeht, haben wir keine andere Möglichkeit, als die Berechnungsmethode der Calculator- Klasse zu ändern .

Daher können wir sagen, dass dieser Code nicht OCP-kompatibel ist.

2.2. OCP-konform

Wie wir gesehen haben, ist unsere Rechner-App noch nicht OCP-kompatibel. Der Code in der Berechnungsmethode ändert sich mit jeder eingehenden neuen Operationsunterstützungsanforderung. Wir müssen diesen Code also extrahieren und in eine Abstraktionsschicht einfügen.

Eine Lösung besteht darin, jede Operation in ihre jeweilige Klasse zu delegieren:

public interface CalculatorOperation { void perform(); }

Infolgedessen könnte die Addition- Klasse die Logik des Hinzufügens von zwei Zahlen implementieren:

public class Addition implements CalculatorOperation { private double left; private double right; private double result; // constructor, getters and setters @Override public void perform() { result = left + right; } }

Ebenso hätte eine aktualisierte Subtraktionsklasse eine ähnliche Logik. Und ähnlich wie Addition und Subtraktion könnten wir als neue Änderungsanforderung die Divisionslogik implementieren :

public class Division implements CalculatorOperation { private double left; private double right; private double result; // constructor, getters and setters @Override public void perform() { if (right != 0) { result = left / right; } } }

Und schließlich muss unsere Calculator- Klasse keine neue Logik implementieren, wenn wir neue Operatoren einführen:

public class Calculator { public void calculate(CalculatorOperation operation) { if (operation == null) { throw new InvalidParameterException("Cannot perform operation"); } operation.perform(); } } 

Auf diese Weise wird die Klasse zur Änderung geschlossen, aber für eine Erweiterung geöffnet .

3. Fazit

In diesem Tutorial haben wir per Definition gelernt, was OCP ist, und dann diese Definition ausgearbeitet. Wir haben dann ein Beispiel für eine einfache Taschenrechneranwendung gesehen, deren Design fehlerhaft war. Zuletzt haben wir das Design gut gemacht, indem wir es an die OCP angepasst haben.

Wie immer ist der Code auf GitHub verfügbar.