What is the Flyweight Pattern?
The Flyweight Pattern is a structural pattern that focuses on sharing objects to reduce memory consumption. Instead of creating thousands of identical objects, you reuse shared instances while storing unique data separately.
Think of it like using a single font object across multiple text elements rather than creating a new font object for each one.
When to Use the Flyweight Pattern?
- When your app creates a huge number of similar objects.
- When memory usage is a concern.
- When object duplication can be avoided by sharing.
Real-World Example in Dart: Tree Rendering in a Game
Imagine a game where we need to render 100,000 trees.
- Each tree has common data: type, texture, color.
- Each tree also has unique data: position (x, y).
We can use Flyweight to share the common data between trees.
Step 1: Define the Flyweight (Shared Object)
class TreeType {
final String name;
final String color;
final String texture;
TreeType(this.name, this.color, this.texture);
void draw(int x, int y) {
print("Drawing $name tree with color $color and texture $texture at ($x, $y)");
}
}
Step 2: Flyweight Factory (Manages Shared Objects)
class TreeFactory {
static final Map<String, TreeType> _treeTypes = {};
static TreeType getTreeType(String name, String color, String texture) {
String key = "$name-$color-$texture";
if (!_treeTypes.containsKey(key)) {
print("Creating new TreeType: $key");
_treeTypes[key] = TreeType(name, color, texture);
}
return _treeTypes[key]!;
}
}
Step 3: Context (Unique State per Object)
class Tree {
final int x;
final int y;
final TreeType type;
Tree(this.x, this.y, this.type);
void draw() {
type.draw(x, y);
}
}
Step 4: Client Code
void main() {
List<Tree> forest = [];
// Create many trees with shared TreeType objects
forest.add(Tree(1, 2, TreeFactory.getTreeType("Oak", "Green", "Rough")));
forest.add(Tree(3, 4, TreeFactory.getTreeType("Oak", "Green", "Rough")));
forest.add(Tree(5, 6, TreeFactory.getTreeType("Pine", "Dark Green", "Smooth")));
forest.add(Tree(7, 8, TreeFactory.getTreeType("Oak", "Green", "Rough")));
for (var tree in forest) {
tree.draw();
}
}
Example Output
Creating new TreeType: Oak-Green-Rough
Creating new TreeType: Pine-Dark Green-Smooth
Drawing Oak tree with color Green and texture Rough at (1, 2)
Drawing Oak tree with color Green and texture Rough at (3, 4)
Drawing Pine tree with color Dark Green and texture Smooth at (5, 6)
Drawing Oak tree with color Green and texture Rough at (7, 8)
Notice that even though we created 4 trees, only 2 TreeType objects were created and shared.
Benefits of Flyweight Pattern
- Huge memory savings when dealing with many similar objects.
- Improves performance by reusing heavy objects.
- Cleaner code with separation of intrinsic state (shared) and extrinsic state (unique).
Drawbacks
- Adds complexity with factories and state management.
- Works best when there’s a lot of repetition in object data.
Flutter Use Cases
- Text rendering: Flutter already uses Flyweight internally for fonts and styles.
- Icons & Images: Sharing the same asset across multiple widgets.
- Game development: Rendering thousands of objects (trees, enemies, bullets).
- Theming: Reusing styles (like
TextStyle,BoxDecoration).
Summary Table
| Attribute | Flyweight Pattern |
|---|---|
| Purpose | Share objects to save memory |
| Common Use Cases | Fonts, themes, game objects, assets |
| Easy in Dart? | Yes, with factories and maps |
| Useful in Flutter? | Especially for UI-heavy or game apps |



