【Java初心者向け】SOLID原則の「O(開放・閉鎖の原則)」をやさしく解説!

こんにちは。ゆうせいです。
今回は、SOLID原則の2つ目「O:開放・閉鎖の原則(Open/Closed Principle)」について、Javaの具体例を交えながら、初学者にもわかりやすく解説していきます。

クラスは変更に対して閉じていて、拡張に対して開いていなければならない」なんて言われると、少し難しく聞こえますよね。
でも安心してください。わかりやすい例実践的なJavaコードで理解していきましょう!


開放・閉鎖の原則(OCP)とは?

定義

ソフトウェアの構成要素(クラスやモジュール)は、拡張には開かれており、修正には閉じているべきである。

つまり、「既存のコードを変更せずに、新しい振る舞いを追加できるように設計しよう!」という考え方です。


なぜ大事なの?

例えば、あなたが一生懸命書いたコードに、あとから別の人が修正を加えた結果、思わぬバグが発生したらイヤですよね?
OCPを意識すれば、既存コードを壊すことなく機能追加ができるので、安全で安心です。


悪い例:OCPを守っていないコード

public class DiscountCalculator {
    public double calculate(String memberType, double amount) {
        if (memberType.equals("gold")) {
            return amount * 0.8; // 20%割引
        } else if (memberType.equals("silver")) {
            return amount * 0.9; // 10%割引
        } else {
            return amount;
        }
    }
}

このコードでは、新しい会員タイプ(たとえば「プラチナ」)を追加したくなったら、クラスの中身を編集する必要があります
これは「変更に対して閉じていない」=OCP違反です。


良い例:OCPを守ったコード(拡張で対応)

1. 抽象クラス(またはインターフェース)を用意

public interface DiscountPolicy {
    double apply(double amount);
}

2. 各種割引の実装クラスを作成

public class GoldDiscount implements DiscountPolicy {
    public double apply(double amount) {
        return amount * 0.8;
    }
}

public class SilverDiscount implements DiscountPolicy {
    public double apply(double amount) {
        return amount * 0.9;
    }
}

public class NoDiscount implements DiscountPolicy {
    public double apply(double amount) {
        return amount;
    }
}

3. 利用側は抽象に依存する

public class DiscountCalculator {
    private final DiscountPolicy policy;

    public DiscountCalculator(DiscountPolicy policy) {
        this.policy = policy;
    }

    public double calculate(double amount) {
        return policy.apply(amount);
    }
}

4. 新しい割引ルールの追加も簡単!

public class PlatinumDiscount implements DiscountPolicy {
    public double apply(double amount) {
        return amount * 0.7;
    }
}

DiscountCalculator クラスは一切変更していませんよね?
このように「新しいクラスを追加するだけで拡張できる」のがOCPの理想です。


図解で理解しよう!

悪い例:条件分岐が増えてしまう良い例:ポリモーフィズムで拡張
if (type == A)DiscountPolicy インターフェースを継承
else if (type == B)GoldDiscount, SilverDiscount, …
新しい種類が出るたびに編集新しいクラスを「追加」するだけ!

OCPを守るための3つのテクニック

テクニック説明
インターフェースの活用実装は差し替え可能にしよう
ストラテジーパターン振る舞いを差し替える代表的なパターン
DI(依存性注入)使う実装を外から渡すことで柔軟に

数式でイメージするなら?

  • 悪い例: 割引金額 = 金額 × 条件分岐による係数
  • 良い例: 割引金額 = 金額 × 実装オブジェクトから得た係数

言葉で書くと:

  • 悪い: 条件ごとに割引ロジックを埋め込む
  • 良い: 割引ロジックは外部のクラスが持つ

まとめと次の学習ステップ

「開放・閉鎖の原則(OCP)」は、変更しない設計によって、安全に拡張可能なソフトウェアを実現するための重要な指針です。

新人エンジニアのうちは、「条件分岐を減らして、拡張できる形にするにはどうすればいいか?」を意識するだけでも大きな前進です!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。