k-tokitoh

2019-05-13

Rubyによるデザインパターン - factory, abstract factory

[![Rubyによるデザインパターン](https://images-fe.ssl-images- amazon.com/images/I/41PNvUxHtgL.SL160.jpg)](http://www.amazon.co.jp/exec/obidos/ASIN/4894712857/hatena- blog-22/)

利用する場面

あるオブジェクトについて、ある場合には a,b,c というクラスを利用したく、別の場合には x,y,z というクラスを利用したい場合。

あれこれ

サンプル

factory パターンから。

class Dinner
  attr_reader :food, :drink
  def initialize
    new_food
    new_drink
  end
end

class Sushi ; end
class Steak ; end
class Sake  ; end
class Wine  ; end

class JapaneseDinner < Dinner
  def new_food
    @food = Sushi.new
  end

  def new_drink
    @drink = Sake.new
  end
end

class WesternDinner < Dinner
  def new_food
    @food = Steak.new
  end

  def new_drink
    @drink = Wine.new
  end
end

j = JapaneseDinner.new
p j.food   # => #<Sushi:0x007fee07832438>
p j.drink  # => #<Sake:0x007fee07832410>

w = WesternDinner.new
p w.food   # => #<Steak:0x007fee07831e98>
p w.drink  # => #<Wine:0x007fee07831e70>

続いて abstract factory パターン。

class Dinner
  attr_reader :food, :drink

  def initialize(dish_factory)
    @dish_factory = dish_factory
    @food = @dish_factory.new_food
    @drink = @dish_factory.new_drink
  end
end

class Sushi ; end
class Steak ; end
class Sake  ; end
class Wine  ; end

class JapaneseDishFactory
  def new_food
    Sushi.new
  end

  def new_drink
    Sake.new
  end
end

class WesternDishFactory
  def new_food
    Steak.new
  end

  def new_drink
    Wine.new
  end
end

j = Dinner.new(JapaneseDishFactory.new)
p j.food   # => #<Sushi:0x007fc075078e00>
p j.drink  # => #<Sake:0x007fc075078dd8>

w = Dinner.new(WesternDishFactory.new)
p w.food   # => #<Steak:0x007fc0750789c8>
p w.drink  # => #<Wine:0x007fc0750787e8>

個々の abstract factory をクラスにせず、インスタンスにしてもよい。

class Dinner
  attr_reader :food, :drink

  def initialize(dish_factory)
    @dish_factory = dish_factory
    @food = @dish_factory.new_food
    @drink = @dish_factory.new_drink
  end
end

class Sushi ; end
class Steak ; end
class Sake  ; end
class Wine  ; end

class DishFactory
  def initialize(food, drink)
    @food = food
    @drink = drink
  end

  def new_food
    @food.new
  end

  def new_drink
    @drink.new
  end
end

japanese_dish_factory = DishFactory.new(Sushi, Sake)
j = Dinner.new(japanese_dish_factory)
p j.food   # => #<Sushi:0x007fc075078e00>
p j.drink  # => #<Sake:0x007fc075078dd8>

western_dish_factory = DishFactory.new(Steak, Wine)
w = Dinner.new(western_dish_factory)
p w.food   # => #<Steak:0x007fc0750789c8>
p w.drink  # => #<Wine:0x007fc0750787e8>