Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Flyweight Pattern

Share objects efficiently - minimize memory usage by sharing intrinsic state!

Now let’s explore the Flyweight Pattern - a powerful structural design pattern that minimizes memory usage by sharing intrinsic state among multiple objects.

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).

The Flyweight Pattern is useful when:

  1. You have many similar objects - That share common data
  2. Memory is a concern - Need to reduce memory usage
  3. Intrinsic state can be shared - Common data that doesn’t change
  4. Extrinsic state is unique - Unique data for each object
  5. 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

Let’s start with a super simple example that anyone can understand!

Diagram

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!

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
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.

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

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

Extrinsic state stored in separate context object:

Pros: Better organization, can store multiple extrinsic values
Cons: More objects to manage


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

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



  1. Memory Efficiency - Shares intrinsic state, reduces memory usage
  2. Reduced Object Creation - Reuses flyweights instead of creating new objects
  3. Scalability - Can handle large numbers of objects efficiently
  4. Performance - Less memory allocation and garbage collection
  5. Separation of Concerns - Clear separation of intrinsic vs extrinsic state

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).

  • 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
  1. Identify intrinsic state - Data that can be shared
  2. Identify extrinsic state - Data that is unique per object
  3. Create flyweight - Stores only intrinsic state
  4. Create factory - Manages flyweight creation and caching
  5. Client uses flyweight - Passes extrinsic state as parameters
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)
class Flyweight:
def __init__(self, intrinsic):
self.intrinsic = intrinsic # Shared
def operation(self, extrinsic):
return f"{self.intrinsic} + {extrinsic}" # Unique

✅ Many similar objects
✅ Memory is a concern
✅ Intrinsic state can be shared
✅ Extrinsic state is unique
✅ Want to reduce object creation

❌ Few objects
❌ No shared state
❌ Extrinsic state is large
❌ Over-engineering

  • 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)
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]
  • 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!

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

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.”

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.”

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

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.”

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! 🪶