← Back to the index page

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.

Factory Method Schema

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        
--]]

Feedback

For feedback, please check the contacts section. Before writing, please specify where you came from and who you are. Sometimes spammers go insane. Thank you in advance for your understanding.

← Back to the index page