Factory Method
The Factory Method is a creational design pattern that defines an interface for creating objects in a super-class, while enabling subclasses to specify the exact type of objects that should be instantiated. In other words, it is a way to create objects without specifying the exact class to instantiate, but create an object of a specific class.
For the demo, let’s create a monster factory which will create a monster of a specific type for the abstract RPG game.
Monster class
First, let’s define our monster classes. There is abstract monster class and its subclasses: Goblin, Skeleton and Demon.
---@class Monster
---@field public name string
---@field public damage number
---@field public hp number
---@field public special string
local Monster = {}
Monster.__index = Monster
---@return Monster
function Monster:new(name, damage, hp, special)
local t = {
name = name,
damage = damage,
hp = hp,
special = special
}
return setmetatable(t, self)
end
---@class Goblin: Monster
local Goblin = {}
---@return Goblin
function Goblin:new()
return Monster:new("Goblin", 2, 10, "None") --[[@as Goblin]]
end
---@class Skeleton: Monster
local Skeleton = {}
---@return Skeleton
function Skeleton:new()
return Monster:new("Skeleton", 4, 12, "Reform") --[[@as Skeleton]]
end
---@class Demon: Monster
local Demon = {}
---@return Demon
function Demon:new()
return Monster:new("Demon", 10, 50, "Fire hit") --[[@as Demon]]
end
MonsterFactory class
Monster factory produces the monsters, depending on the type. In this pattern, you should not care about constructors of the monster, but just to create a monster by type. This method is invaluable when there are not too many monsters yet. But more if-elseif statements will be added for more types of monster you have. Here comes in handy another design pattern: Abstract factory.
---@class MonsterFactory
local MonsterFactory = {}
---@return MonsterFactory
function MonsterFactory:create(type)
if type == "Goblin" then
return Goblin:new()
elseif type == "Skeleton" then
return Skeleton:new()
elseif type == "Demon" then
return Demon:new()
else
error("unknown monster")
end
end
Usage of MonsterFactory
local goblin = MonsterFactory:create("Goblin")
print(goblin.name, goblin.damage, goblin.hp, goblin.special)
local skelly = MonsterFactory:create("Skeleton")
print(skelly.name, skelly.damage, skelly.hp, skelly.special)
local demon = MonsterFactory:create("Demon")
print(demon.name, demon.damage, demon.hp, demon.special)
--[[
Goblin 2 10 None
Skeleton 4 12 Reform
Demon 10 50 Fire hit
--]]
