2019-05-13
Rubyによるデザインパターン - factory, abstract factory
[](http://www.amazon.co.jp/exec/obidos/ASIN/4894712857/hatena- blog-22/)
利用する場面
あるオブジェクトについて、ある場合には a,b,c というクラスを利用したく、別の場合には x,y,z というクラスを利用したい場合。
あれこれ
- factory パターンとは、template method パターンをクラスの選択(及びインスタンスの生成)に関して適用した場合の呼び名。
- すなわち、サブクラスを用意してサブクラスの中でそれぞれ適切なクラスを選択して利用する。
- abstract factory パターンとは、strategy パターンをクラスの選択(及びインスタンスの生成)に関して適用した場合の呼び名。
- すなわち、インスタンス生成を行う。
サンプル
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>