structural
Flyweight
Use sharing to support large numbers of fine-grained objects efficiently by separating shared intrinsic state from per-object extrinsic state.
Problem
A system creates a large number of similar objects, but storing all of their state separately uses too much memory.
Integration notes
Flyweight is useful when thousands or millions of similar objects need to be represented efficiently, such as trees, glyphs, tiles, or UI tokens.
Tradeoffs
- Adds complexity because state must be split into shared and unshared parts
- Can be harder to understand when many objects depend on an external context
Languages
typescript, java, python, angular, react, react-native, csharp, dotnet
Platforms
Web, Backend, Mobile, UI kits, Cross-platform systems
Variants
Scenarios
Tree rendering flyweight
A forest renderer shares tree type data across many individual tree instances to minimize memory usage.
Language examples
Core languages
Frameworks and libraries
The tree flyweight shares tree type data like color and texture, while each tree instance stores only its position in the forest.
interface TreeType {
render(x: number, y: number): string;
}
class SharedTreeType implements TreeType {
constructor(
private name: string,
private color: string,
private texture: string,
) {}
render(x: number, y: number): string {
return `Tree ${this.name} at (${x}, ${y}) with ${this.color} leaves and ${this.texture} texture`;
}
}
class TreeTypeFactory {
private types = new Map<string, SharedTreeType>();
getTreeType(name: string, color: string, texture: string): SharedTreeType {
const key = `${name}|${color}|${texture}`;
if (!this.types.has(key)) {
this.types.set(key, new SharedTreeType(name, color, texture));
}
return this.types.get(key)!;
}
}
class Tree {
constructor(
private x: number,
private y: number,
private type: TreeType,
) {}
draw(): string {
return this.type.render(this.x, this.y);
}
}
const factory = new TreeTypeFactory();
const pine = factory.getTreeType("Pine", "green", "rough");
const oak = factory.getTreeType("Oak", "dark green", "bark");
const forest = [
new Tree(10, 20, pine),
new Tree(15, 22, pine),
new Tree(30, 40, oak),
];
console.log(forest.map((tree) => tree.draw()).join("\n"));Real-world examples
- Forest rendering: Games and simulations often reuse one tree model or texture definition across thousands of placed trees.
- Text glyph caching: Text renderers commonly share glyph shapes or font data while each character instance stores only placement details.
- Tile maps: Strategy games and editors often reuse terrain definitions and store only tile position and runtime state per cell.