Ruby デザインパターン Strategy


概要

  • Strategy パターンとは
    • 処理をほかのオブジェクトに移譲する
    • 移譲されたオブジェクトを再利用できる
    • 移譲されたオブジェクトそれぞれに共通のインターフェースを持たせることで、オブジェクトを交換して挙動を変えられる

    • いろいろな種類の鴨がいる
    • どれも「鳴く」メソッドを持っているが、種類によって鳴き声が違う
    • そこで「鳴き方オブジェクト」を作って鴨に持たせる
      • 「ガアガア」オブジェクト
      • 「グエグエ」オブジェクト
      • など
    • 鴨の「鳴く」メソッドは実際には鳴き方オブジェクトの「鳴く」メソッドを呼び出すだけ
    • 鳴き方オブジェクトを再代入することで、実行中に動的に鳴き方を変えることもできる

実装

  • やや乱暴だが大体こんな感じ
    • 鳴き方クラスの共通の親クラスを作り、親クラスの quack() は例外を返すようにすると実装漏れが防げる
# 鳴き方クラス(抽象風)

class Quack
  def quack
    raise
  end
end

# 鳴き方クラス(具象風)

class Gaagaa < Quack
  def quack
    puts "gaagaa"
  end
end

class Guegue < Quack
  def quack 
    puts "guegue"
  end
end

# 鴨

class Duck
  attr_writer :voice
  def perform_quack
    @voice.quack 
  end
end

d = Duck.new

d.voice = Gaagaa.new
d.perform_quack # => gaagaa

d.voice = Guegue.new
d.perform_quack # => guegue
  • 挙動を変えるという意味では、module を使ってもよいのでは?と思ったが、それだと挙動の動的変更ができない。
# 鳴き方モジュール

module Gaagaa
  private
  def quack
    puts "gaagaa"
  end
end

module Guegue
  private
  def quack
    puts "guegue"
  end
end

# 鴨

class Duck
  include Guegue
  def perform_quack
    quack
  end
end

d = Duck.new
d.perform_quack # => guegue

# gaagaa 鳴くように変更できない!