Strategyパターン(GoF)

参考書籍一覧(Amazon アソシエイトリンク)

インスタンスを指定して処理をすげ替えたい場合に使うパターン。

開放閉鎖原則であげたツリー構造の探索アルゴリズムの切り替えの例がStrategyパターンに当てはまる。

Strategyクラスを作る例はそちらを参照してもらうとして、ここでは、Strategyクラスを作らずに関数による処理のすげ替えの例をあげる。

class Product
  attr_accessor :price, :discount_function

  def initialize(name, price)
    @name = name
    @price = price
    @discount_function = ->(_product) { @price }
  end

  def discount_price
    @discount_function.call(self)
  end
end

このProductクラスはdiscount_functionをすげ替えることで、値引き後金額を変えることができる。

product = Product.new('商品', 1000)
product.discount_function = ->(product) { product.price - 100 }
product.discount_price # => 900

# クロージャーと組み合わせる
current_user = User.find
product.discount_function = lambda do |product|
  return product.price - 500 if current_user.special?

  product.price
end
product.discount_price # => スペシャルユーザーなら500

すげ替える方法に関数を使うかクラスを使うかは、異なる内容ですげ替える箇所がいくつかあって決まった組み合わせですげ替えるかどうかで判断できる。

決まった組み合わせでないなら関数を個別に使えば良いし、決まった組み合わせなら組み合わせごとにクラスを用意すれば良い。

無名関数ではなく、広く使われる関数があるなら定数で持ってしまうなどの方法が考えられる。

class Product
  # 新春セールで100円引き
  NEW_YEAR_SALE = ->(product) { product.price - 100 }
  # ...
end