1. 概要

このチュートリアルでは、オブジェクト指向プログラミングの SOLID原則の1つとして、オープン/クローズド原則(OCP)について説明します。

全体として、この原則とは何か、およびソフトウェアを設計するときにそれを実装する方法について詳しく説明します。

2. オープン/クローズド原則

名前が示すように、この原則は、ソフトウェアエンティティは拡張のために開いているが、変更のために閉じている必要があることを示しています。その結果、ビジネス要件が変更された場合、エンティティは拡張できますが、変更できません。

以下の図では、インターフェイスがOCPを追跡する1つの方法であることに焦点を当てます。

2.1. 非準拠

足し算や引き算など、いくつかの操作ができる電卓アプリを作成しているとしましょう。

まず、トップレベルのインターフェイスを定義します– CalculatorOperation

public interface CalculatorOperation {}

Addition クラスを定義してみましょう。このクラスは、2つの数値を加算し、C alculatorOperationを実装します。

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

}

現在のところ、クラス Addition、は1つしかないため、Subtractionという名前の別のクラスを定義する必要があります。

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
}

次に、電卓の操作を実行するメインクラスを定義しましょう。 

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());
        }
    }
}

これは問題ないように見えるかもしれませんが、OCPの良い例ではありません。 乗算または除算機能を追加するという新しい要件が発生した場合、 計算するの方法電卓クラス。

したがって、このコードはOCPに準拠していないと言えます。

2.2. OCP準拠

これまで見てきたように、電卓アプリはまだOCPに準拠していません。 calculate メソッドのコードは、新しい操作のサポートリクエストが着信するたびに変更されます。 したがって、このコードを抽出して抽象化レイヤーに配置する必要があります。

1つの解決策は、各操作をそれぞれのクラスに委任することです。

public interface CalculatorOperation {
    void perform();
}

その結果、 Addition クラスは、次の2つの数値を加算するロジックを実装できます。

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;
    }
}

同様に、更新されたSubtractionクラスも同様のロジックを持ちます。 また、加算および減算と同様に、新しい変更要求として、除算ロジックを実装できます。

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;
        }
    }
}

そして最後に、 Calculator クラスは、新しい演算子を導入するときに新しいロジックを実装する必要はありません。

public class Calculator {

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

そうすれば、クラスは変更のために閉じられ、拡張のために開かれます

3. 結論

このチュートリアルでは、定義によるOCPとは何かを学び、その定義について詳しく説明しました。 次に、設計に欠陥のある単純な計算機アプリケーションの例を見ました。 最後に、OCPに準拠させることでデザインを良くしました。

いつものように、コードはGitHubから入手できます。