Author:
Factory Method⚓︎
"I know what 'type' I need, but which specific subclass to
newis left to the subclass to decide."
Characteristics⚓︎
- Define an interface for creating an object.
- Let subclasses decide which class to instantiate.
- Defer instantiation to subclasses.
Factory Method vs Abstract Factory
Factory Method: each concrete factory creates one concrete product (e.g., CircleFactory → Circle, RectangleFactory → Rectangle).- `Abstract Factory: used to create families of related products together (e.g., a UI theme producing matching Button and Checkbox variants).
e.g: Boba shop⚓︎
Boba shop makes milk tea.
Shanghai Boba shop only makes Taro Milk Tea.
Beijing Boba shop only makes Matcha Milk Tea.
Hands dirty - "Enemy Spawner"⚓︎
We want to create different types of enemies (e.g., Goblin, Troll) in a game. The specific enemy type to spawn is determined by the game level.
Meaning of ←
A dashed arrowhead line indicates a class that instantiates objects of another class. The arrow points to the class of the instantiated objects
We want the code deciding which enemy to spawn at runtime, in Main():
- Get level from config
- Choose concrete factory (GoblinFactory or TrollFactory) based on level
- Inject factory into Game (Compose concrete factory in Game over Inheritance)
-
Factory creates specific Enemy
using System; public interface IEnemy { void Attack(); } public class Goblin : IEnemy { public void Attack() => Console.WriteLine("Goblin attacks with a club!"); } public class Troll : IEnemy { public void Attack() => Console.WriteLine("Troll attacks with a hammer!"); } public abstract class EnemyFactory { public abstract IEnemy CreateEnemy(); } public class GoblinFactory : EnemyFactory { public override IEnemy CreateEnemy() => new Goblin(); } public class TrollFactory : EnemyFactory { public override IEnemy CreateEnemy() => new Troll(); } // Client code using dependency injection: pass a concrete factory to `Game`. class Game { private EnemyFactory factory; public Game(EnemyFactory factory) { this.factory = factory; } public void Run() { IEnemy enemy = factory.CreateEnemy(); enemy.Attack(); } static void Main() { // Compose application with a concrete factory string level = GetLevelFromConfig(); // e.g. "Forest", "Cave" EnemyFactory factory = level switch { "Forest" => new GoblinFactory(), "Cave" => new TrollFactory(), _ => new GoblinFactory() }; var game = new Game(factory); game.Run(); } }#include <iostream> #include <memory> #include <string> class IEnemy { public: virtual void attack() const = 0; virtual ~IEnemy() = default; }; class Goblin : public IEnemy { public: void attack() const override { std::cout << "Goblin attacks with a club!\n"; } }; class Troll : public IEnemy { public: void attack() const override { std::cout << "Troll attacks with a hammer!\n"; } }; class EnemyFactory { public: virtual std::unique_ptr<IEnemy> createEnemy() const = 0; virtual ~EnemyFactory() = default; }; class GoblinFactory : public EnemyFactory { public: std::unique_ptr<IEnemy> createEnemy() const override { return std::make_unique<Goblin>(); } }; class TrollFactory : public EnemyFactory { public: std::unique_ptr<IEnemy> createEnemy() const override { return std::make_unique<Troll>(); } }; // Client code using dependency injection: provide a concrete factory to `Game`. class Game { public: explicit Game(std::unique_ptr<EnemyFactory> f) : factory(std::move(f)) {} void run() const { auto enemy = factory->createEnemy(); enemy->attack(); } private: std::unique_ptr<EnemyFactory> factory; }; int main() { std::string level = getLevelFromConfig(); // "Forest" / "Cave" std::unique_ptr<EnemyFactory> factory; if (level == "Forest") factory = std::make_unique<GoblinFactory>(); else if (level == "Cave") factory = std::make_unique<TrollFactory>(); else factory = std::make_unique<GoblinFactory>(); Game game(std::move(factory)); game.run(); }

