References:
Refactoring Guru - Flyweight Pattern
Original Korean post
What is the Flyweight Pattern?
The Flyweight Pattern is a structural design pattern that saves memory by sharing common parts of state between multiple objects, instead of keeping all data in each object. In other words, it is a caching technique for objects.
Situation
Imagine a shooting game where players fire various types of projectiles: bullets, missiles, and shotgun shells. Shortly after starting, the game runs out of memory and crashes.
Cause of the Problem
Each projectile (particle) has its own x, y coordinates, vector, speed, color, and image. Every time a new bullet is created, all these properties are stored in memory. For example, if each bullet takes up 21KB, then 1 million bullets would consume 21GB of memory!
Solution – Share Common Elements Among Objects!
Let’s analyze the properties of a bullet:
- Each bullet has unique
x, y coordinates,vector, andspeed. These are called extrinsic state (values that change per object). - However, the
colorandimageare the same for all bullets of the same type. These are called intrinsic state (fixed values).
The Flyweight pattern ensures that only the intrinsic state is stored in the shared object, and the extrinsic state is passed in as needed. Objects that only contain intrinsic state are called flyweights.
Refactoring the example:
- The
Particleclass only contains intrinsic properties like color and sprite. - Extrinsic properties are separated into a
MovingParticleclass. - The
MovingParticleholds a reference to a sharedParticleobject, saving memory by not duplicating intrinsic data. - The
Gameclass manages the creation and sharing of intrinsic objects, so new particles can reference existing ones. - The origin particle is selected by the
MovingParticlesobject, and extrinsic values are passed to theParticle’s methods as needed.
Implementation Note
Since intrinsic state is shared across different contexts, it must be immutable.
Structure
In the example, the Game class is responsible for both resource management and creation, but typically, this responsibility is delegated to a FlyweightFactory (using the Factory Method pattern).
The term original object refers to the fact that the object’s properties have been split into intrinsic and extrinsic parts.
1. FlyweightFactory
- Responsible for creating and managing flyweight objects.
- Only creates a new flyweight if one does not already exist for the requested state.
2. Flyweight
- Holds the shared (intrinsic) state.
- Methods accept unique (extrinsic) state as parameters.
3. Context
- Represents the combination of intrinsic and extrinsic state.
- Can be implemented in two ways:
- The flyweight object has a method that takes extrinsic state and performs operations. The context passes extrinsic state to the flyweight.
- The context class itself implements the operation, and the flyweight is just a data holder.
4. Client
- Calculates and stores extrinsic state.
- From the client’s perspective, the flyweight is a template that can be used with different runtime data.
- For example, in a shooting game, the user’s character fires a bullet (extrinsic: position) and the bullet image (intrinsic) is shared.
Example Code – Drawing Trees
Forest
| |
Tree
| |
TreeType
| |
TreeFactory
| |
Notes
- When reusing objects in different contexts, always ensure intrinsic state is immutable.
- The Flyweight pattern is often used with the Composite pattern to share leaf nodes.
Translated from jurogrammer.tistory.com/114