Factory Pattern
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 47 of 65.
The Factory pattern moves the choice of which class to create into one place. The rest of the program asks the factory for "a goblin" and gets an object back, without naming the class Goblin.
The products share a parent class, so the code that uses them works with any of them:
# enemy.gd
class_name Enemy
extends RefCounted
var hp := 10
func attack() -> String:
return "The enemy waits"# goblin.gd
class_name Goblin
extends Enemy
func attack() -> String:
return "The goblin stabs"# orc.gd
class_name Orc
extends Enemy
func attack() -> String:
return "The orc smashes"The factory is a class with a static func that turns a name into an object. Its return type is the parent class, so it can return any kind of enemy, or null for a name it does not know:
# enemy_factory.gd
class_name EnemyFactory
extends RefCounted
static func create(kind: String) -> Enemy:
match kind:
"goblin":
return Goblin.new()
"orc":
return Orc.new()
return null# main.gd
for kind in ["orc", "goblin", "slime"]:
var enemy := EnemyFactory.create(kind)
if enemy == null:
print("Unknown enemy: ", kind)
else:
print(enemy.attack())The orc smashes
The goblin stabs
Unknown enemy: slimeNames like these usually come from data: a spawn table, a level file, a command the player typed. The factory is the only place that maps them to classes, so adding a Dragon takes one new file and one new branch in the match.
A factory can also set the object up before returning it, so every caller gets an enemy that is ready to use:
static func create_boss(kind: String, level: int) -> Enemy:
var boss := create(kind)
if boss != null:
boss.hp = 100 * level
return bossEnemyFactory.create_boss("orc", 3) returns an Orc with 300 HP.
Challenge
MediumA spawn table names enemies and levels. Enemy (enemy.gd) and its subclass Goblin (goblin.gd) are written; finish the rest:
- In
orc.gd, the constructor_init(level)passes the nameOrc,25 * levelHP and4 + leveldamage to the parent constructor, the wayGoblindoes. - In
enemy_factory.gd,static func create(kind, level)returns aGoblinforgoblinand anOrcfororc, created with that level. Upper-case letters in the name do not matter (ORCis an orc). Any other name returnsnull.
The supplied code reads how many spawns follow, then one KIND LEVEL line per spawn, and prints each enemy or Unknown enemy: KIND, then how many enemies were spawned. For goblin 2, Orc 3 and slime 1 the output is:
Goblin: 20 HP, 4 damage
Orc: 75 HP, 7 damage
Unknown enemy: slime
Spawned: 2Your code goes in enemy_factory.gd and orc.gd. main.gd holds the supplied input/output code and cannot be edited.
Try it yourself
extends Node
func _ready():
# Supplied input/output code: keep it as it is
var spawned := 0
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
var enemy := EnemyFactory.create(parts[0], int(parts[1]))
if enemy == null:
print("Unknown enemy: ", parts[0])
else:
spawned += 1
print(enemy.describe())
print("Spawned: ", spawned)
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe self KeywordMethodsPropertiesConstructor (_init)Recap - Simple Calculator4Polymorphism
Method Overriding RevisitedDuck TypingAbstract Classes and MethodsInterface DesignRecap - Shape Calculator2Class Properties
Instance vs Static VariablesStatic FunctionsProperty SettersProperty GettersPrivate by ConventionRecap - Bank Account Manager5Encapsulation
Public and Private MembersValidation with SettersInformation HidingRead-Only PropertiesRecap - Student Records System8Advanced OOP Concepts
Composition vs InheritanceInner ClassesNodes as ComponentsRefCounted vs NodeEnums in Classes11Project: Library Management
Project OverviewBook and User Classes3Inheritance
Basic InheritanceThe super KeywordMethod OverridingInheritance ChainsType Checks with isRecap - Employee Hierarchy6Special Methods
Virtual Methods IntroductionThe _to_string MethodCustom IteratorsRecap - Custom List9Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy PatternPractice on your own: Online GDScript compiler