Card 01/ 08
Flyweight Pattern: Sharing Common State Across Many Objects
A forest of a million trees needs only a few tree types, each stored once.
The Flyweight pattern lets a program hold a very large number of small objects by sharing the part of each that is the same. That shared part is stored once, in an object called the flyweight, and every object that needs it holds a reference to it. This card covers the problem, the split between shared and varying state that the pattern rests on, and when it fits.
The problem is memory spent on repetition. A forest in a game holds a million trees, and each tree object stores its species name, its mesh, its bark texture and its position. Only the position differs between trees of one species, so almost all of the memory holds copies of the same few values.
Without the patternevery tree holds everything
class Tree:
def __init__(self, x, y, species, mesh, texture):
self.x, self.y = x, y
self.species = species
self.mesh = mesh
self.texture = textureA million trees hold a million copies of a few meshes and textures.
With the patternevery tree points at its type
class TreeType:
def __init__(self, species, mesh, texture): ...
class Tree:
def __init__(self, x, y, kind: TreeType):
self.x, self.y = x, y
self.kind = kindA million trees share one TreeType per species, and each stores two numbers and a reference.
The Gang of Four state the intent as: use sharing to support large numbers of fine-grained objects efficiently. The pattern rests on dividing an object's state in two.
- Intrinsic state is the same wherever the object is used, such as a species' mesh. It lives inside the flyweight and is shared.
- Extrinsic state depends on where the object is used, such as a tree's position. It stays outside the flyweight, held by the caller or passed in on each call.
Because many users hold the same flyweight, it must be immutable, unable to change after it is created. A change made through one tree would otherwise change every tree of that species.
Flyweight is one of seven structural patterns, the family that composes classes and objects into larger structures.
| Pattern | What it does |
|---|---|
| Adapter | Gives an existing object the interface a client expects. |
| Bridge | Separates an abstraction from its implementation so both can vary. |
| Composite | Treats a tree of objects and a single object the same way. |
| Decorator | Adds behaviour by wrapping an object in another with the same interface. |
| Facade | Puts one simple interface in front of a complex subsystem. |
| Flyweight (this topic) | Shares the common part of many small objects to save memory. |
| Proxy | Stands in for an object to control access to it. |
Use it when
- A program holds a very large number of objects, and memory is the measured problem.
- Most of each object's state is repeated across many others.
- The repeated state can be made immutable, and the rest can be passed in or held outside.
Avoid it when
- There are hundreds of objects rather than hundreds of thousands, so the saving is too small to matter.
- The shared part must change per object, so it cannot be made immutable.
- Code compares the objects by identity, which sharing changes.
← → move through sections and cards