Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Flyweight Pattern

Intent

Use sharing to support large numbers of fine-grained objects efficiently. Minimize memory usage by sharing common state (intrinsic) across objects while keeping unique state (extrinsic) separate.

Intrinsic vs Extrinsic State

AspectIntrinsic StateExtrinsic State
Shared?Yes — stored in the flyweightNo — passed by the client
Independent of context?YesNo
Memory impactAmortized across all usersPer-object
ExampleTree species (name, color, texture)Position, size of each tree instance

Implementation

class TreeStyle:
    """Intrinsic state — shared across all trees of the same species."""
    def __init__(self, name, color, texture):
        self.name = name
        self.color = color
        self.texture = texture

class TreeFactory:
    """Flyweight factory — ensures sharing."""
    _styles = {}

    @classmethod
    def get_style(cls, name, color, texture):
        key = (name, color, texture)
        if key not in cls._styles:
            cls._styles[key] = TreeStyle(name, color, texture)
        return cls._styles[key]

    @classmethod
    def style_count(cls):
        return len(cls._styles)

class Tree:
    """Extrinsic state — unique per tree instance."""
    def __init__(self, x, y, style: TreeStyle):
        self.x = x
        self.y = y
        self.style = style

    def draw(self):
        print(f'{self.style.name} at ({self.x},{self.y})')

# 10,000 trees but only 3 shared styles
styles = [('Oak', 'green', 'rough'), ('Pine', 'dark green', 'smooth'), ('Birch', 'white', 'peeling')]
trees = []
for i in range(10000):
    s = styles[i % 3]
    style = TreeFactory.get_style(*s)
    trees.append(Tree(i % 500, i // 500, style))

print(f'Styles created: {TreeFactory.style_count()}')  # 3, not 10000

String Interning

Python and Java automatically intern short strings — identical string literals share the same object. This is a built-in flyweight optimization.

a = "hello"
b = "hello"
print(a is b)  # True — same object (interned)

When to Use

  • A large number of objects consume significant memory.
  • Most object state can be made extrinsic.
  • The application doesn’t depend on object identity (shared references are fine).

Interview Questions

Q: What’s the difference between intrinsic and extrinsic state? A: Intrinsic state is shared and context-independent (stored in the flyweight). Extrinsic state is unique per instance and passed in by the client at use time. Only intrinsic state is stored in the shared pool.

Q: When is flyweight inappropriate? A: When objects have mostly unique state (little to share), when object identity matters (e.g., identity maps), or when the overhead of the factory and extrinsic parameter passing exceeds the memory savings.

Q: How does string interning relate to the flyweight pattern? A: String interning is a specific application of the flyweight pattern. The runtime maintains a pool of unique strings; identical literals map to the same object, saving memory and enabling O(1) equality checks via reference comparison.

References