Factory Functions
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 62 of 70.
Throughout this course, you've created objects by calling constructors directly—Circle:new(), Rectangle:new(), and so on. But what if you want to create different types of objects based on some condition, without the calling code needing to know which specific class to use?
This is where the Factory pattern comes in. A factory is simply a function that creates and returns objects. The key benefit is that the caller doesn't need to know the details of object creation—it just asks the factory for what it needs.
local function createShape(shapeType)
if shapeType == "circle" then
return Circle:new(10)
elseif shapeType == "square" then
return Square:new(5)
end
end
-- The caller doesn't need to know about Circle or Square classes
local myShape = createShape("circle")
print(myShape:area())
The factory function takes a string argument and decides which class to instantiate. This centralizes object creation logic in one place. If you later add a new shape type, you only modify the factory—not every piece of code that creates shapes.
Factories are especially useful when object creation involves complex setup, when you want to hide implementation details, or when the exact type of object depends on runtime conditions like user input or configuration files.
Challenge
EasyLet's build a Pet Factory! Instead of creating pets directly by calling each class's constructor, you'll create a factory function that produces the right type of pet based on a simple string argument.
You'll organize your code across four files:
Dog.lua: Create a Dog class with a:new(name)constructor that stores the pet's name. Add a:speak()method that returns the string"{name} says: Woof!"(where {name} is the dog's name).Cat.lua: Create a Cat class with the same structure—a:new(name)constructor and a:speak()method that returns"{name} says: Meow!".PetFactory.lua: This is where the Factory pattern shines! Create acreatePet(petType, name)function that takes two arguments: a string indicating the pet type ("dog"or"cat") and the pet's name. The function should return the appropriate pet object. If the type is"dog", return a new Dog; if"cat", return a new Cat.main.lua: Require your PetFactory module. Read two inputs: the pet type and the pet's name. Use your factory function to create the pet, then call its:speak()method and print the result.
The beauty of the Factory pattern is that your main code doesn't need to require Dog or Cat directly—it only knows about the factory. The factory handles all the details of which class to instantiate.
You will receive two inputs:
- Pet type (either
"dog"or"cat") - Pet name (a string)
For example, if the inputs are dog and Buddy, the output should be:
Buddy says: Woof!If the inputs are cat and Whiskers, the output should be:
Whiskers says: Meow!Cheat sheet
The Factory pattern is a design pattern where a function creates and returns objects based on given parameters. The caller doesn't need to know which specific class is being instantiated—the factory handles that decision.
A factory function centralizes object creation logic:
local function createShape(shapeType)
if shapeType == "circle" then
return Circle:new(10)
elseif shapeType == "square" then
return Square:new(5)
end
end
local myShape = createShape("circle")
print(myShape:area())
Benefits of the Factory pattern:
- Hides implementation details from the caller
- Centralizes object creation in one place
- Makes it easy to add new types—only the factory needs modification
- Useful when object type depends on runtime conditions (user input, configuration, etc.)
- Helpful when object creation involves complex setup
Try it yourself
-- main.lua
-- Use the PetFactory to create pets
local PetFactory = require('PetFactory')
-- Read inputs
local petType = io.read()
local petName = io.read()
-- TODO: Use PetFactory.createPet to create the pet
-- TODO: Call the pet's :speak() method and print the result
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy