アブストラクトファクトリは、矛盾のないオブジェクトの生成を行うためのパターンです。
このアブストラクトファクトリをRubyコードで紹介します。
😀 ソースコードを使ったAbstract Factoryの説明
Abstract Factoryをソースコードを使って説明します。
ここでは次のような池をサンプルとして取り上げます。
動物を表すクラス:
- アヒルを表すDuckクラスは、食事(eat)メソッドを持っている
- カエルを表すFrogクラスは、食事(eat)メソッドを持っている
植物を表すクラス:
- 藻を表すAlgaeクラスは、成長(grow)メソッドを持っている
- スイレンを表すWaterLilyクラスは、成長(grow)メソッドを持っている
池の生態系を生成するクラス:
- コンストラクタで動物と植物を定義する
- 動物、植物のオブジェクトを返すメソッドを持っている
- 池の環境(動物と植物の組み合わせ)は次の2種類のみが許されている
- DuckとWaterLily
- FrogとAlgae
🚌 サンプルコード
アヒル(Duckクラス)とカエル(Frogクラス)は次のようになります。
class Duck def initialize(name) @name = name end
def eat puts "アヒル #{@name} は食事中です" end end
class Frog def initialize(name) @name = name end
def eat puts "カエル #{@name} は食事中です" end end
|
一方、藻(Algaeクラス)とスイレン(WaterLilyクラス)のは次のようになります。
class Algae def initialize(name) @name = name end
def grow puts "藻 #{@name} は成長中です" end end
class WaterLily def initialize(name) @name = name end
def grow puts "スイレン #{@name} は成長中です" end end
|
次に池を作成する前に、「池の環境の制約」について考えます。
- 池の環境(動物と植物の組み合わせ)は2種類のみが許されている
- アヒル(Duckクラス)とスイレン(WaterLilyクラス)
- カエル(Frogクラス)と藻(Algaeクラス)
この池の環境の制約を守ること、言い換えると矛盾のないオブジェクトの組み合わせを作るのが「Abstract Factoryパターン」です。
今回はこの矛盾のない環境の作成を次の2つのクラスに担当してもらいます。
- カエル(Frog)と藻(Algae)の生成を行う =>
FrogAndAlgaeFactory
- アヒル(Duck)とスイレン(WaterLily)の生成を行う =>
DuckAndWaterLilyFactory
さらに上の2つのクラスのベースとなる池の生態系を表すクラスOrganismFactory
を作り、上記のクラスが継承するようにします。
ということで、ソースコードはこちら。
class OrganismFactory def initialize(number_animals, number_plants) @animals = [] number_animals.times do |i| animal = new_animal("動物 #{i}") @animals << animal end
@plants = [] number_plants.times do |i| plant = new_plant("植物 #{i}") @plants << plant end end
def get_plants @plants end
def get_animals @animals end end
class FrogAndAlgaeFactory < OrganismFactory private
def new_animal(name) Frog.new(name) end
def new_plant(name) Algae.new(name) end end
class DuckAndWaterLilyFactory < OrganismFactory private
def new_animal(name) Duck.new(name) end
def new_plant(name) WaterLily.new(name) end end
|
🏀 実行結果
プログラムを実行した結果は次のとおりです。
factory = FrogAndAlgaeFactory.new(4,1) animals = factory.get_animals animals.each { |animal| animal.eat }
plants = factory.get_plants plants.each { |plant| plant.grow }
factory = DuckAndWaterLilyFactory.new(3,2) animals = factory.get_animals animals.each { |animal| animal.eat }
plants = factory.get_plants plants.each { |plant| plant.grow }
|
矛盾のない組み合わせて、オブジェクトを生成できたことがわかります。
🍄 Abstract Factoryの構成
Abstract Factoryは次の3つの要素で構成されています。
AbstractFactory
:ConcreteFactoryの共通部分の処理を行う
ConcreteFactory
:実際にオブジェクトの生成を行う
Product
:ConcreteFactoryによって生成される側のオブジェクト
🤔 アブストラクトファクトリのメリットは?
- 関連し合うオブジェクトの集まりを生成できる
- 整合性が必要となるオブジェクト群を誤りなしに生成できる
🚕 GitHubリポジトリ
😼 参考リンク
🖥 VULTRおすすめ
「VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。
最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!