ファクトリ関数
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 62/70。
このコースを通して、これまでコンストラクタを直接呼び出してオブジェクトを作成してきました:Circle:new()、Rectangle:new()などです。しかし、呼び出し元のコードが使用する具体的なクラスを知る必要なく、ある条件に基づいて異なる種類のオブジェクトを作成したい場合はどうでしょうか?
ここでFactoryパターンの出番です。ファクトリーとは、オブジェクトを作成して返す単純なfunctionです。主な利点は、callerがオブジェクト作成の詳細を知る必要がないことです。callerは必要なものをファクトリーに尋ねるだけです。
local function createShape(shapeType)
if shapeType == "circle" then
return Circle:new(10)
elseif shapeType == "square" then
return Square:new(5)
end
end
-- 呼び出し側は Circle や Square クラスについて知る必要がない
local myShape = createShape("circle")
print(myShape:area())
factory function は文字列の引数を受け取り、どの class をインスタンス化するかを決定します。これにより、object の作成ロジックを 1 か所に集約できます。後から新しい図形の種類を追加する場合は、図形を作成するすべてのコードを変更するのではなく、factory だけを変更すれば済みます。
ファクトリは、object の作成に複雑なセットアップが必要な場合、実装の詳細を隠したい場合、または object の正確な型がユーザー入力や設定ファイルなどの実行時の条件によって決まる場合に、特に便利です。
チャレンジ
簡単Pet Factory を作りましょう!各クラスの constructor を呼び出して直接 pet を作成する代わりに、単純な文字列の引数に基づいて適切な種類の pet を生成する Factory function を作成します。
コードを4つのファイルに分けて整理します。
Dog.lua::new(name)constructor を持つ Dog class を作成し、pet の名前を保存します。"{name} says: Woof!"という文字列を返す:speak()method を追加します({name} は dog の名前です)。Cat.lua: 同じ構造の Cat class を作成します。:new(name)constructor と、"{name} says: Meow!"を返す:speak()method を持たせます。PetFactory.lua: ここで Factory pattern が活躍します!2つの引数を受け取るcreatePet(petType, name)function を作成します。引数は、pet の種類を示す文字列("dog"または"cat")と pet の名前です。function は適切な pet object を返します。種類が"dog"の場合は新しい Dog を、"cat"の場合は新しい Cat を返します。main.lua: PetFactory module を require します。2つの入力、つまり pet の種類と pet の名前を read します。Factory function を使って pet を作成し、その:speak()method を call して result を print します。
Factory pattern の利点は、main code で Dog や Cat を直接 require する need がないことです。main code が know しているのは Factory だけです。どの class を instantiate するかに関するすべての詳細は Factory が処理します。
2つの入力を受け取ります。
- Pet の種類(
"dog"または"cat") - Pet の名前(文字列)
たとえば、inputs が dog と Buddy の場合、output は次のようになります。
Buddy says: Woof!inputs が cat と Whiskers の場合、output は次のようになります。
Whiskers says: Meow!自分で試してみよう
-- main.lua
-- PetFactoryを使ってペットを作成する
local PetFactory = require('PetFactory')
-- 入力を読み取る
local petType = io.read()
local petName = io.read()
-- TODO: PetFactory.createPetを使ってペットを作成する
-- TODO: ペットの:speak()メソッドを呼び出して結果を出力する
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ