Vapor Trail

明るく楽しく元気よく

『Head Firstデザインパターン』 Chapter1 デザインパターンの根底にあるオブジェクト指向の原則

はじめの状態

共通の処理を抽象クラスに書きサブクラスが継承する。 いわゆる差分プログラミング。

飛ぶ振る舞いをもたせる必要が出てきた

飛ぶ振る舞いを基底クラスに追加したがDuckのすべてのサブクラスが飛ぶ必要はない。 コードに対する局所的な更新によって、非局所的な副作用が発生してしまった。
再利用を目的とした継承は保守の観点ではあまり適切ではない。
すべてのサブクラスが飛ぶ振る舞いや鳴く振る舞いを持つべきではないことがわかっているので、継承は正しい解決策ではない。

継承ではなくインターフェースを使ってみても問題は解決しない

継承ではなくインターフェースとして実装しても、インターフェースは振る舞いに対してコードの再利用ができないので問題は一部しか解決しない。

不変な部分から変化する部分を分離する

不変な部分から変化する部分を分離するためにクラスを作成する。
fly()とquack()は鴨の種類ごとに変化するDuckクラスの一部だということがわかっている。
これらの振る舞いをDuckクラスから分離するため、これらのメソッドをDuckクラスから取り出し、それぞれの振る舞いを表す新しいクラスを作成する。

振る舞いを設計する

  • 柔軟性を保つこと
    この設計では飛ぶ振る舞いや鳴く振る舞いがDuckのサブクラス内に隠蔽されなくなるので、別の方のオブジェクトがこれらの振る舞いを再利用できる。また、既存の振る舞いクラスを変更したり、Duckのサブクラスに触れたりすることなく、新しい振る舞いを追加できる。

  • 重要なのはDuckクラスで定義されたfly()メソッドやquack()メソッドを使用する代わりに鳴く振る舞いや飛ぶ振る舞いを委譲するようになること。

鴨は振る舞いを継承する代わりに適切な振る舞いオブジェクトで構成されることで振る舞いを取得する。

設計原則

  1. アプリケーション内の変化する部分を特定し、不変な部分と分離する。
    コードの変化する部分を把握すれば、変化しないすべての部分から取り出して分離する必要のある振る舞いがわかる。
    変化する部分を取り出しカプセル化する。そうすれば不変な部分に影響を与えずに変化する部分を後で変更したり拡張できる。
    すべてのデザインパターンはシステムのある部分をその他のすべての部分と独立して変更できるようにする方法を提供する。

  2. 実装に対してではなくインターフェースに対してプログラミングする
    柔軟性を保つこと。実装に対してではなく抽象に対してプログラミングすること。

  3. 継承よりコンポジションを好む
    コンポジションを使ってシステムを作成すると柔軟性が上がる。

抽象化、継承、ポリモーフィズムの概念を知っているからといって優れたオブジェクト指向設計者になれるわけではない。
保守性があり変更に対応できる柔軟な設計を作成できることが重要。
保守性のあるシステムを作成するための秘訣は、システムが将来どのように変化する可能性があるか考えること。