Flyweight Pattern
Flyweight Pattern: Sharing Objects Efficiently
Section titled “Flyweight Pattern: Sharing Objects Efficiently”Now let’s explore the Flyweight Pattern - a powerful structural design pattern that minimizes memory usage by sharing intrinsic state among multiple objects.
Why Flyweight Pattern?
Section titled “Why Flyweight Pattern?”Imagine you’re playing a video game with thousands of trees. Each tree has the same texture, color, and shape (intrinsic state), but different positions (extrinsic state). Instead of storing thousands of tree objects with duplicate data, you store one tree object and share it! The Flyweight Pattern works the same way - it shares common data (intrinsic state) and stores unique data (extrinsic state) separately.
The Flyweight Pattern uses sharing to support large numbers of fine-grained objects efficiently. It separates intrinsic state (shared) from extrinsic state (unique).
What’s the Use of Flyweight Pattern?
Section titled “What’s the Use of Flyweight Pattern?”The Flyweight Pattern is useful when:
- You have many similar objects - That share common data
- Memory is a concern - Need to reduce memory usage
- Intrinsic state can be shared - Common data that doesn’t change
- Extrinsic state is unique - Unique data for each object
- You want to reduce object creation - Share objects instead of creating new ones
What Happens If We Don’t Use Flyweight Pattern?
Section titled “What Happens If We Don’t Use Flyweight Pattern?”Without the Flyweight Pattern, you might:
- High memory usage - Each object stores all data, even if shared
- Object explosion - Creating many similar objects wastes memory
- Poor performance - More objects means more memory allocation
- Wasted resources - Duplicate data stored multiple times
- Scalability issues - Can’t handle large numbers of objects
Simple Example: The Text Editor
Section titled “Simple Example: The Text Editor”Let’s start with a super simple example that anyone can understand!
Visual Representation
Section titled “Visual Representation”Interaction Flow
Section titled “Interaction Flow”Here’s how the Flyweight Pattern works in practice - showing how flyweights are shared:
sequenceDiagram
participant Client
participant Factory as FlyweightFactory
participant Flyweight as CharacterFlyweight
participant Context as CharacterContext
Client->>Factory: get_flyweight('A')
activate Factory
Factory->>Factory: Check if 'A' exists
alt 'A' doesn't exist
Factory->>Flyweight: Create new Character('A')
activate Flyweight
Flyweight-->>Factory: Character('A')
deactivate Flyweight
Factory->>Factory: Store in cache
end
Factory-->>Client: Character('A')
deactivate Factory
Client->>Context: Create context(x=10, y=20)
activate Context
Context-->>Client: Context
deactivate Context
Client->>Flyweight: render(context)
activate Flyweight
Flyweight->>Flyweight: Use intrinsic: 'A'
Flyweight->>Flyweight: Use extrinsic: x, y from context
Flyweight-->>Client: Rendered 'A' at (10, 20)
deactivate Flyweight
Note over Client,Context: Same flyweight reused\nwith different contexts!
The Problem
Section titled “The Problem”You’re building a text editor. You need to render thousands of characters. Without Flyweight Pattern:
Problems:
- High memory usage - Each object stores all data, even shared data
- Object explosion - Creating many similar objects wastes memory
- Duplicate data - Same intrinsic data stored multiple times
- Poor scalability - Can’t handle large numbers of objects efficiently
The Solution: Flyweight Pattern
Section titled “The Solution: Flyweight Pattern”Class Structure
Section titled “Class Structure”classDiagram
class FlyweightFactory {
-flyweights: Map
+get_flyweight(key) Flyweight
}
class Flyweight {
<<interface>>
+operation(extrinsic) void
}
class ConcreteFlyweight {
-intrinsic_state: string
+operation(extrinsic) void
}
class UnsharedConcreteFlyweight {
-all_state: string
+operation(extrinsic) void
}
class Client {
+operation() void
}
Client --> FlyweightFactory : uses
FlyweightFactory --> Flyweight : creates/returns
Flyweight <|.. ConcreteFlyweight : implements
Flyweight <|.. UnsharedConcreteFlyweight : implements
Client --> Flyweight : uses with extrinsic state
note for ConcreteFlyweight "Stores intrinsic state (shared)"
note for Client "Provides extrinsic state (unique)"
Real-World Software Example: Game Tree Rendering
Section titled “Real-World Software Example: Game Tree Rendering”Now let’s see a realistic software example - a game that needs to render thousands of trees efficiently.
The Problem
Section titled “The Problem”You’re building a game that needs to render thousands of trees. Each tree has the same texture and model (intrinsic), but different positions (extrinsic). Without Flyweight Pattern:
Problems:
- High memory usage - Each tree stores texture and model separately
- Duplicate data - Same intrinsic data stored 1000 times
- Poor scalability - Can’t handle large numbers efficiently
The Solution: Flyweight Pattern
Section titled “The Solution: Flyweight Pattern”Flyweight Pattern Variants
Section titled “Flyweight Pattern Variants”There are different ways to implement the Flyweight Pattern:
1. Intrinsic/Extrinsic Separation (Standard)
Section titled “1. Intrinsic/Extrinsic Separation (Standard)”Intrinsic state in flyweight, extrinsic state passed as parameters:
Pros: Clear separation, efficient
Cons: Need to pass extrinsic state each time
2. Context Object
Section titled “2. Context Object”Extrinsic state stored in separate context object:
Pros: Better organization, can store multiple extrinsic values
Cons: More objects to manage
When to Use Flyweight Pattern?
Section titled “When to Use Flyweight Pattern?”Use Flyweight Pattern when:
✅ You have many similar objects - That share common data
✅ Memory is a concern - Need to reduce memory usage
✅ Intrinsic state can be shared - Common data that doesn’t change
✅ Extrinsic state is unique - Unique data for each object
✅ You want to reduce object creation - Share objects instead of creating new ones
When NOT to Use Flyweight Pattern?
Section titled “When NOT to Use Flyweight Pattern?”Don’t use Flyweight Pattern when:
❌ Few objects - If you have few objects, overhead isn’t worth it
❌ No shared state - If objects don’t share common data
❌ Extrinsic state is large - If extrinsic state is larger than intrinsic
❌ Over-engineering - Don’t add complexity for simple cases
Common Mistakes to Avoid
Section titled “Common Mistakes to Avoid”Mistake 1: Not Separating Intrinsic and Extrinsic State
Section titled “Mistake 1: Not Separating Intrinsic and Extrinsic State”Mistake 2: Not Using Factory
Section titled “Mistake 2: Not Using Factory”Mistake 3: Storing Too Much in Intrinsic State
Section titled “Mistake 3: Storing Too Much in Intrinsic State”Benefits of Flyweight Pattern
Section titled “Benefits of Flyweight Pattern”- Memory Efficiency - Shares intrinsic state, reduces memory usage
- Reduced Object Creation - Reuses flyweights instead of creating new objects
- Scalability - Can handle large numbers of objects efficiently
- Performance - Less memory allocation and garbage collection
- Separation of Concerns - Clear separation of intrinsic vs extrinsic state
Revision: Quick Catch-Up
Section titled “Revision: Quick Catch-Up”What is Flyweight Pattern?
Section titled “What is Flyweight Pattern?”Flyweight Pattern is a structural design pattern that uses sharing to support large numbers of fine-grained objects efficiently. It separates intrinsic state (shared) from extrinsic state (unique).
Why Use It?
Section titled “Why Use It?”- ✅ Memory efficiency - Shares intrinsic state, reduces memory usage
- ✅ Reduced object creation - Reuses flyweights instead of creating new objects
- ✅ Scalability - Can handle large numbers of objects efficiently
- ✅ Performance - Less memory allocation and garbage collection
- ✅ Separation - Clear separation of intrinsic vs extrinsic state
How It Works?
Section titled “How It Works?”- Identify intrinsic state - Data that can be shared
- Identify extrinsic state - Data that is unique per object
- Create flyweight - Stores only intrinsic state
- Create factory - Manages flyweight creation and caching
- Client uses flyweight - Passes extrinsic state as parameters
Key Components
Section titled “Key Components”Client → FlyweightFactory → Flyweight (intrinsic) + Extrinsic State- Flyweight - Stores intrinsic state (shared)
- FlyweightFactory - Creates and manages flyweights
- Client - Provides extrinsic state (unique)
- Intrinsic State - Shared data (e.g., character, texture)
- Extrinsic State - Unique data (e.g., position, color)
Simple Example
Section titled “Simple Example”class Flyweight: def __init__(self, intrinsic): self.intrinsic = intrinsic # Shared
def operation(self, extrinsic): return f"{self.intrinsic} + {extrinsic}" # UniqueWhen to Use?
Section titled “When to Use?”✅ Many similar objects
✅ Memory is a concern
✅ Intrinsic state can be shared
✅ Extrinsic state is unique
✅ Want to reduce object creation
When NOT to Use?
Section titled “When NOT to Use?”❌ Few objects
❌ No shared state
❌ Extrinsic state is large
❌ Over-engineering
Key Takeaways
Section titled “Key Takeaways”- Flyweight Pattern = Shares intrinsic state, stores extrinsic separately
- Intrinsic = Shared data (stored in flyweight)
- Extrinsic = Unique data (passed as parameters)
- Benefit = Memory efficiency, scalability
- Use Case = Many similar objects (text editors, games, graphics)
Common Pattern Structure
Section titled “Common Pattern Structure”class Flyweight: def __init__(self, intrinsic): self.intrinsic = intrinsic
def operation(self, extrinsic): return f"{self.intrinsic} + {extrinsic}"
class Factory: def __init__(self): self.cache = {}
def get_flyweight(self, key): if key not in self.cache: self.cache[key] = Flyweight(key) return self.cache[key]Remember
Section titled “Remember”- Flyweight Pattern shares intrinsic state
- It separates intrinsic from extrinsic state
- Use a factory to manage flyweights
- It’s about memory efficiency, not just sharing!
- Only store truly shared data in intrinsic state!
Interview Focus: Flyweight Pattern
Section titled “Interview Focus: Flyweight Pattern”Key Points to Remember
Section titled “Key Points to Remember”1. Core Concept
Section titled “1. Core Concept”What to say:
“Flyweight Pattern is a structural design pattern that uses sharing to support large numbers of fine-grained objects efficiently. It separates intrinsic state (shared data) from extrinsic state (unique data), storing only intrinsic state in the flyweight object.”
Why it matters:
- Shows you understand the fundamental purpose
- Demonstrates knowledge of intrinsic vs extrinsic state
- Indicates you can explain concepts clearly
2. When to Use Flyweight Pattern
Section titled “2. When to Use Flyweight Pattern”Must mention:
- ✅ Many similar objects - That share common data
- ✅ Memory is a concern - Need to reduce memory usage
- ✅ Intrinsic state can be shared - Common data that doesn’t change
- ✅ Extrinsic state is unique - Unique data for each object
Example scenario to give:
“I’d use Flyweight Pattern when building a text editor that needs to render thousands of characters. Each character ‘A’ has the same shape and font (intrinsic), but different positions (extrinsic). Instead of creating 1000 ‘A’ objects, I create one ‘A’ flyweight and reuse it with different positions. This saves significant memory.”
3. Intrinsic vs Extrinsic State
Section titled “3. Intrinsic vs Extrinsic State”Must discuss:
- Intrinsic State: Shared data stored in flyweight (e.g., character, texture, model)
- Extrinsic State: Unique data passed as parameters (e.g., position, color)
- Key difference: Intrinsic is shared, extrinsic is unique
Example to give:
“In a game with trees, intrinsic state includes texture and model (same for all oak trees), while extrinsic state includes position (unique per tree). The flyweight stores texture and model, and position is passed when rendering.”
4. Benefits and Trade-offs
Section titled “4. Benefits and Trade-offs”Benefits to mention:
- Memory efficiency - Shares intrinsic state, reduces memory usage
- Reduced object creation - Reuses flyweights instead of creating new objects
- Scalability - Can handle large numbers of objects efficiently
- Performance - Less memory allocation and garbage collection
Trade-offs to acknowledge:
- Complexity - Adds abstraction layer
- Factory overhead - Need to manage flyweight cache
- Not suitable for few objects - Overhead not worth it for small numbers
5. Common Interview Questions
Section titled “5. Common Interview Questions”Q: “What’s the difference between Flyweight Pattern and Object Pool Pattern?”
A:
“Flyweight Pattern shares intrinsic state among many objects to reduce memory usage. Object Pool Pattern reuses entire objects to avoid expensive creation. Flyweight is about sharing data, Object Pool is about reusing objects. Flyweight separates intrinsic/extrinsic state, Object Pool manages a pool of ready-to-use objects.”
Q: “How do you determine what should be intrinsic vs extrinsic state?”
A:
“Intrinsic state is data that is the same across many objects and doesn’t change. Extrinsic state is data that is unique per object or changes frequently. If data is shared and immutable, it’s intrinsic. If data is unique or mutable, it’s extrinsic. For example, character shape is intrinsic (same for all ‘A’s), position is extrinsic (unique per ‘A’).”
Q: “How does Flyweight Pattern relate to memory management?”
A:
“Flyweight Pattern reduces memory usage by sharing common data. Instead of storing duplicate data in each object, it stores shared data once and reuses it. This reduces memory footprint, especially when you have many similar objects. It also reduces garbage collection pressure by creating fewer objects.”
Interview Checklist
Section titled “Interview Checklist”Before your interview, make sure you can:
- Define Flyweight Pattern clearly in one sentence
- Explain intrinsic vs extrinsic state (with examples)
- Describe when to use it (with examples showing memory savings)
- Implement Flyweight Pattern from scratch
- Compare with other patterns (Object Pool, Singleton)
- List benefits and trade-offs
- Identify common mistakes (not separating state, no factory)
- Give 2-3 real-world examples
- Discuss memory management implications
- Explain when NOT to use it
Remember: Flyweight Pattern is about sharing intrinsic state efficiently - reducing memory usage by sharing common data among many objects! 🪶