■継承より集約
# 継承のごく簡単なサンプル class Vehicle # 乗り物に関するたくさんのコード... def start_engine # エンジンスタート end def stop_engine # エンジンストップ end end class Car < Vehicle def sunday_drive start_engine # 地方に出かけ、戻ってくる stop_engine end end
■何が問題になるか ?
上のコードだと、全ての乗り物(Vehicle)がエンジンを持っていることが必要になる。
もしエンジンの無い乗り物、例えばヨットとかを扱うとなると、このクラスに大きな変更を施さなくてはならなくなる。
これでは、原則である「変わらないものを変わるものから分離する」に従っていない。
そこで「集約」という概念が出てくる
class Engine # エンジンに関するたくさんのコード... def start # エンジンスタート end def stop # エンジンストップ end end class Car def initialize @engine = Engine.new end def sunday_drive @engine.start # 地方に出かけ戻ってくる @engine.stop end end
上のコードでは、継承ではなく「集約」を利用している。
変わりやすい部分(ここではエンジン)を変わらない部分から分離するため、この部分の記述をCarのスーパークラスの中に作るのではなく、完全にスタンドアロンなクラスとして作る。
CarオブジェクトにそれぞれEngineの参照を与えさえすれば、集約のおかげでドライブの準備が整う。
■委譲、委譲、委譲
# 委譲のごく簡単なサンプル class Car def initialize @engine = GasolineEngine.new end def sunday_drive @engine.start # 地方に出かけ、戻ってくる @engine.stop end def switch_to_diesel @engine = DieselEnegine.new end def start_engine @engine.start end def stop_engine @engine.stop end end
何者かがCarのstart_engineメソッドを呼ぶと、Carオブジェクトは「私の担当ではない」と言って、
バトンをEngineに手渡す。このような責任転嫁のテクニックを「委譲」と呼ぶ。
上述のコードでは、委譲をふんだんに利用している。
集約と委譲の組み合わせは、継承に対するとても強力で柔軟な代替手段になりうる。
継承の利点の多くを持ちつつ、より柔軟で、問題となる副作用も無い。
全くの0コストというわけではないが、それが大きな問題になる可能性は少い。