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