MogLog

メモというか日記というか備忘録というか

『Rubyによるデザインパターン』学習ノート:「継承より集約」「委譲、委譲、委譲」

■継承より集約

# 継承のごく簡単なサンプル
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コストというわけではないが、それが大きな問題になる可能性は少い。