「Rubyによるデザインパターン」の読書メモです。
Abstract Factory
Factory Method パターンがTemplate Method パターンをオブジェクトの作成に適用したのと同じように、Abstract Factory パターンは同じ問題にStrategyパターンを適用したのです。
アブストラクトファクトリで大事なことは、どの製品の型が一緒になるのかという知識をカプセル化することなのです。
class Duck
def initialize(name)
@name = name
end
def eat
puts "アヒル #{@name} は食事中です。"
end
def speak
puts "アヒル #{@name} はガーガー鳴いています。"
end
def sleep
puts "アヒル #{@name} は静かに眠っています。"
end
end
class Frog
def initialize(name)
@name = name
end
def eat
puts "カエル #{@name} は食事中です。"
end
def speak
puts "カエル #{@name} はゲロゲロっと鳴いています。"
end
def sleep
puts "カエル #{@name} は眠りません。一晩中ゲロゲロ鳴いています。"
end
end
class Algae
def initialize(name)
@name = name
end
def grow
p "藻 #{@name} は日光を浴びて育ちます。"
end
end
class WaterLily
def initialize(name)
@name = name
end
def grow
p "睡蓮 #{@name} は浮きながら日光を浴びて育ちます。"
end
end
class Tree
def initialize(name)
@name = name
end
def grow
p "樹木 #{@name} が高く育っています。"
end
end
class Tiger
def initialize(name)
@name = name
end
def eat
puts "トラ #{@name} は食べたいものを何でも食べます。"
end
def speak
puts "トラ #{@name} はガオーとほえています。"
end
def sleep
puts "トラ #{@name} は眠くなったら眠ります。"
end
end
class PondOrganismFactory
def new_animal(name)
Frog.new(name)
end
def new_plant(name)
Algae.new(name)
end
end
class JungleOrganismFactory
def new_animal(name)
Tiger.new(name)
end
def new_plant(name)
Tree.new(name)
end
end
class Habitat
def initialize(number_animals, number_plants, organism_factory)
@organism_factory = organism_factory
@animals = []
number_animals.times do |i|
animal = @organism_factory.new_animal("動物#{i}")
@animals << animal
end
@plants = []
number_plants.times do |i|
plant = @organism_factory.new_plant("植物#{i}")
@plants << plant
end
end
def simulate_one_day
@plants.each {|plant| plant.grow}
@animals.each {|animal| animal.speak}
@animals.each {|animal| animal.eat}
@animals.each {|animal| animal.sleep}
end
end
jungle = Habitat.new(1, 4, JungleOrganismFactory.new)
jungle.simulate_one_day
pond = Habitat.new(2, 4, PondOrganismFactory.new)
pond.simulate_one_day
Factory の一段上のレイヤーで、組み合わせを担っています。
まとめ
「どのクラスを選ぶのか?」という問いに答えるための技術です。