Factory pattern
Overview
A Factory is a function or class that creates objects for you. Instead of creating objects directly, you ask the Factory for what you need. Imagine a restaurant kitchen. You do not go into the kitchen and make a pizza yourself. You give an order to the kitchen staff, and they give you a finished pizza. A Factory works the same way. You give it a name, and it gives you the right object. Here is a Factory for a food app: ```python class Pizza: def serve(self): return "Serving Pizza" class Burger: def serve(self): return "Serving Burger" # This is the Factory function def create_food(food_type): if food_type == "pizza": return Pizza() elif food_type == "burger": return Burger() ``` Now, we ask the Factory to create the food for us: ```python my_food = create_food("pizza") print(my_food.serve()) ``` The code that uses `create_food` does not need to know how `Pizza` or `Burger` are made. Let us practice. Here is a faded example. Fill in the blank to ask the Factory for a burger. ```python # We want a burger object my_lunch = ____("burger") ``` The rule to remember: **A Factory takes a simple input (like a string) and returns a complex object.** There is a sharp edge to this pattern. Every time you invent a new food (like "Pasta"), you must remember to open the Factory function and add a new `elif` line. If your app has 100 foods, this function becomes very long and messy.
If object creation is complex (like reading database settings first), a Factory hides that mess. Your main code stays clean because it only calls the Factory.
Where used: Building user interface buttons, Loading different database types, Parsing different file formats (CSV, JSON)
Why learn this
- You will understand how large apps create objects cleanly.
- You will write code that is easier to update when new features are added.
Code walkthrough
class TextMsg:
type = "text"
class ImageMsg:
type = "image"
def message_factory(msg_type):
if msg_type == "image":
return ImageMsg()
return TextMsg()
msg = message_factory("image")
print(msg.type)
Focus: return ImageMsg()
Aha moment
class Admin:
role = "Admin"
class Guest:
role = "Guest"
def create_user(is_admin):
if is_admin:
return Admin
return Guest
user = create_user(True)
print(user.role)
Prediction: What does this print? Look closely at what the factory returns.
Common guess: It crashes or prints an error.
A Factory can return the CLASS itself, not just an object! In Python, classes are just objects too. The factory returns the `Admin` class, and we access `.role` directly.
Common mistakes
- Using a Factory for everything: If a class is very simple and has no complex setup, you do not need a Factory. Just create the object directly.
- Factory doing too much work: A Factory should only create objects. If it also saves data to the database or sends emails, it is doing too much and will break easily.
Recall questions
- Explain the Factory pattern in your own words, as if to a classmate.
- Why would you use a Factory instead of creating objects directly?
- What happens to a simple Factory function if you add 50 new types of objects?
Understanding checks
What does this code print?
Riding bike
The Factory receives the input `2`. It checks the condition, creates a `Bike` object, and returns it. The main code then calls `ride()` on the `Bike`.
A developer is writing code to parse a file. The file can be a `.csv` or a `.json`. How does a Factory help here?
A Factory can take the file extension as input and return the correct parser object.
This keeps the main code clean. The main code just asks the Factory for a parser and does not need to know the complex steps to build each specific parser.
Practice tasks
Add a new format
Given this Factory, modify the function so that if `format` is `'pdf'`, it returns a `PdfDocument()` object.
Continue learning
Previous: Class Creation and Instantiation