Creational patterns (Singleton, Factory, Builder) in Software Engineering - Time & Space Complexity
When using creational patterns like Singleton, Factory, and Builder, it's important to understand how the time to create objects grows as the program runs.
We want to know how the cost of creating objects changes when we create many of them.
Analyze the time complexity of creating multiple objects using a Factory pattern.
class Product {
constructor(name) {
this.name = name;
}
}
class ProductFactory {
createProduct(name) {
return new Product(name);
}
}
const factory = new ProductFactory();
for (let i = 0; i < n; i++) {
factory.createProduct(`Product${i}`);
}
This code creates n products using a Factory. Each product is a simple object with a name.
Look at what repeats when creating many objects.
- Primary operation: Calling
createProductto make a new object. - How many times: Exactly n times, once for each product.
Each new product takes about the same time to create, so total time grows as we make more products.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 object creations |
| 100 | 100 object creations |
| 1000 | 1000 object creations |
Pattern observation: The time grows directly with the number of objects created.
Time Complexity: O(n)
This means if you double the number of objects, the time to create them roughly doubles too.
[X] Wrong: "Using a Factory or Builder makes object creation instant or constant time regardless of how many objects."
[OK] Correct: Each object still needs to be created one by one, so total time grows with the number of objects, even if the pattern helps organize the code.
Understanding how object creation scales helps you explain design choices clearly and shows you grasp both design and performance, a useful skill in real projects.
What if the Factory cached and reused objects instead of creating new ones each time? How would the time complexity change?
Practice
Solution
Step 1: Understand the Singleton pattern purpose
The Singleton pattern restricts the instantiation of a class to one object only.Step 2: Compare with other patterns
Factory creates objects but does not limit the number; Builder constructs complex objects step-by-step; Prototype clones objects.Final Answer:
Singleton -> Option AQuick Check:
Only one instance = Singleton [OK]
- Confusing Factory with Singleton
- Thinking Builder limits instances
- Mixing Prototype with Singleton
Solution
Step 1: Recall Singleton implementation details
Singleton classes hide their constructor (make it private) to prevent direct instantiation.Step 2: Provide controlled access
A static method returns the single instance, creating it if it doesn't exist yet.Final Answer:
Make the constructor private and provide a static method to get the instance -> Option CQuick Check:
Private constructor + static getter = Singleton [OK]
- Allowing public constructors in Singleton
- Using factory method to create multiple instances
- Confusing Builder with Singleton syntax
class AnimalFactory {
createAnimal(type) {
switch(type) {
case 'dog': return new Dog();
case 'cat': return new Cat();
default: return null;
}
}
}
const factory = new AnimalFactory();
const pet = factory.createAnimal('dog');
console.log(pet.sound());What will be the output if
Dog.sound() returns "Woof" and Cat.sound() returns "Meow"?Solution
Step 1: Understand the Factory method call
The factory creates an object based on the string 'dog', so it returns a new Dog instance.Step 2: Call the sound method on the Dog instance
Since Dog.sound() returns "Woof", the console.log outputs "Woof".Final Answer:
"Woof" -> Option DQuick Check:
Factory creates Dog, Dog.sound() = "Woof" [OK]
- Assuming factory returns null for known types
- Confusing Dog and Cat outputs
- Thinking createAnimal is undefined
class Logger {
constructor() {
if (!Logger.instance) {
Logger.instance = this;
}
return Logger.instance;
}
}
const log1 = new Logger();
const log2 = new Logger();
console.log(log1 === log2);What is the output and what is the issue with this Singleton implementation?
Solution
Step 1: Analyze the constructor logic
The constructor checks if Logger.instance exists; if not, assigns this to it, then returns Logger.instance.Step 2: Check the instance equality
Both log1 and log2 refer to the same Logger.instance, so log1 === log2 is true.Step 3: Identify the issue
The constructor is still public, so new Logger() can be called multiple times, which is not ideal for Singleton pattern.Final Answer:
true; but constructor is public which is not ideal -> Option BQuick Check:
Same instance but public constructor = A [OK]
- Assuming public constructor is fine for Singleton
- Thinking output is false due to new calls
- Expecting runtime error on instance assignment
Solution
Step 1: Understand the problem requirements
The object is complex with many optional parts, so building it step-by-step is needed.Step 2: Match with creational patterns
Builder pattern is designed to construct complex objects step-by-step, allowing optional parts without confusing client code.Step 3: Exclude other patterns
Singleton limits instances, Factory creates objects but not stepwise, Prototype clones existing objects.Final Answer:
Builder -> Option AQuick Check:
Step-by-step complex object = Builder [OK]
- Choosing Singleton for complex object creation
- Using Factory when stepwise building is needed
- Confusing Prototype cloning with building
Ready to prove it?
Pass the test and this pattern moves unknown
