Flyweight pattern
The flyweight pattern minimizes memory by sharing common state across thousands of objects, splitting data into intrinsic (shared) and extrinsic (unique) parts.
Introduction
The Flyweight pattern reduces repeated memory by separating state that can be shared from state that belongs to one object. A flyweight stores reusable, context-independent data; a lightweight context stores the unique data for each occurrence.
TL;DR / mental model: Cache one immutable object for each repeated intrinsic-state combination, keep per-instance extrinsic state outside it, and pass that state in when the shared object is used.
Problem and Context
You're building a game that renders a forest with 10,000 trees. Each tree object stores its sprite texture, color palette, mesh data, position, and scale. The textures and meshes are identical for every oak tree, but you're allocating them per instance.
Three tree species, 10,000 total trees. 99.9% of the allocated memory is duplicated data that never changes between instances of the same species. The problem is not the trees, it is the failure to separate what is shared from what is unique.
When It Helps
Flyweight helps when many objects repeat the same heavyweight, context-independent data and profiling shows that duplication is costly. It is a poor fit when most state is unique, mutable, or difficult to separate cleanly.
Here is what changes when you apply the Flyweight pattern.
Participants and Structure
Participants
- Flyweight:
TreeType, holding the shared intrinsic state and using supplied context when it renders. - Flyweight factory:
TreeTypeFactory, which maps a state key such as a species name to a shared flyweight. - Context:
Tree, holding extrinsic state such as position and scale plus a flyweight reference. - Client:
Forest, which requests flyweights, creates contexts, and supplies extrinsic state at use time.
TreeType is the flyweight. It holds the heavy, immutable intrinsic state (sprite, mesh, palette) shared across all trees of the same species. Tree is the lightweight context that holds only the extrinsic state (position, scale) unique to each instance. TreeTypeFactory caches a TreeType for each species so repeated requests can reuse it. Forest wires everything together, planting trees that reference shared flyweights.
The memory math: 3 species x 7MB = 21MB of shared data, plus 10,000 trees x 24 bytes (x, y, scale, reference) = 240KB. Total: roughly 21MB instead of 70GB.
Idiomatic Example and Implementation Notes
The key insight is identifying which state is intrinsic (shared, immutable, context-independent) and which is extrinsic (unique per instance, supplied at runtime). The pattern may help when many objects carry identical heavyweight data.
Intrinsic vs extrinsic state
Intrinsic state lives inside the flyweight and should be immutable from callers' point of view. If it contains arrays or collections, keep them encapsulated or make defensive copies. Extrinsic state lives outside and is passed in by the caller. If the split is wrong, sharing will not provide the intended savings.
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with SDEpedia Premium.
Related Articles
The prototype pattern creates new objects by cloning existing ones, avoiding expensive construction when you need many similar instances with minor variations.
The factory method replaces direct constructor calls with a method that subclasses can override to return different types. Callers depend on an abstraction, not a concrete class.
The singleton restricts a class to one instance within a chosen scope and provides an access point. Thread-safe initialization, serialization safety, and testability are important design concerns.