Use sharing to efficiently support a massive number of fine-grained objects by separating shared (intrinsic) state from unique (extrinsic) state.
The Flyweight pattern is a memory optimisation technique for when you need to create massive numbers of similar objects. It separates each object's state into two parts: intrinsic state (shared, stored in the flyweight) and extrinsic state (unique, passed in at runtime).
Think of rendering a forest with a million trees: every Oak tree looks identical — same texture, same shape. Instead of storing the texture in each of a million tree objects, you store it once in a shared "OakType" flyweight, and each tree only stores its unique position. Memory: from millions of large objects to a handful of flyweights + millions of tiny contexts.
This is a performance pattern — you only need it when memory or object creation cost is a genuine bottleneck. It adds complexity, so apply it only at scale.
Key Idea: What's shared goes in the Flyweight (intrinsic). What's unique is passed in as context (extrinsic). One flyweight serves thousands of contexts.
This distinction is the heart of Flyweight. Get it wrong and the pattern won't work:
Shared across all objects of the same type. Stored inside the flyweight. Immutable — must not change or other users of the flyweight are affected.
✓ Stored once, shared by all instances
Unique to each object instance. Stored in a lightweight context object or passed into flyweight methods. Changes per instance.
✓ Stored in tiny context, passed to flyweight
Test: If two objects of the same "type" share the same value for a field regardless of where/when they are created — it's intrinsic. If the value can differ between instances — it's extrinsic.
Stores intrinsic (shared, immutable) state. Receives extrinsic state as method parameters when performing operations. Must be immutable — any mutation would affect all sharers.
Creates and manages flyweight objects. Uses a pool/cache to return existing flyweights when the same intrinsic state is requested. Ensures proper sharing.
A lightweight object per instance that stores the unique extrinsic state and holds a reference to the shared flyweight. Not always a formal class — extrinsic state can be passed directly.
Gets flyweights from the factory, stores/passes extrinsic state, and calls flyweight operations with the extrinsic context each time.
// Flyweight Pattern — Forest Rendering (10 million trees)
// ─── Flyweight — stores SHARED (intrinsic) state ──────────────
class TreeType {
private final String name;
private final String colour;
private final String texture; // heavy data — loaded once
public TreeType(String name, String colour, String texture) {
this.name = name;
this.colour = colour;
this.texture = texture;
System.out.println("[FlyweightFactory] Created TreeType: " + name);
}
// Context (extrinsic state) passed in — not stored here
public void draw(int x, int y) {
System.out.printf("[Render] %s tree at (%d,%d) colour=%s%n", name, x, y, colour);
}
}
// ─── Flyweight Factory — ensures sharing ──────────────────────
class TreeTypeFactory {
private static java.util.Map<String, TreeType> cache = new java.util.HashMap<>();
public static TreeType getTreeType(String name, String colour, String texture) {
String key = name + "_" + colour;
if (!cache.containsKey(key)) {
cache.put(key, new TreeType(name, colour, texture));
} else {
System.out.println("[FlyweightFactory] Reusing TreeType: " + name);
}
return cache.get(key);
}
public static int getCacheSize() { return cache.size(); }
}
// ─── Context — stores UNIQUE (extrinsic) state ────────────────
class Tree {
private final int x, y; // unique per tree
private final TreeType type; // shared flyweight
public Tree(int x, int y, TreeType type) {
this.x = x; this.y = y; this.type = type;
}
public void draw() { type.draw(x, y); }
}
// ─── Client ───────────────────────────────────────────────────
public class App {
public static void main(String[] args) {
java.util.List<Tree> forest = new java.util.ArrayList<>();
java.util.Random rnd = new java.util.Random();
String[] types = {"Oak", "Pine", "Birch"};
String[] colours = {"#2D5A1B", "#1B3D2D", "#8B7355"};
// Plant 1,000,000 trees — only 3 TreeType objects created!
for (int i = 0; i < 1_000_000; i++) {
int idx = rnd.nextInt(3);
TreeType type = TreeTypeFactory.getTreeType(
types[idx], colours[idx], "texture_" + types[idx] + ".png"
);
forest.add(new Tree(rnd.nextInt(5000), rnd.nextInt(5000), type));
}
System.out.println("\nTrees planted: " + forest.size());
System.out.println("TreeType objects created: " + TreeTypeFactory.getCacheSize());
System.out.println("Memory saved: ~" + (1_000_000 - 3) + " TreeType objects!");
// Draw a few trees
forest.subList(0, 3).forEach(Tree::draw);
}
}When an application creates hundreds of thousands or millions of objects that share significant common state. Memory footprint becomes a genuine problem.
Forest trees, text characters, map tiles, particlesWhen profiling shows object creation or memory is a bottleneck — Flyweight can reduce memory use by orders of magnitude.
10M tree objects → 3 TreeType flyweightsParticle systems, terrain tiles, character sprites, map objects — all benefit from sharing the expensive graphical/physics data.
ParticleSystem, TileMap, NPC spritesEach character glyph in a large document shares font/style data. Only position and colour differ per character instance.
CharacterGlyph, FontRenderer, DocumentLayoutJava interns string literals — "hello" at two places in code shares one object. String.intern() explicitly adds to the pool. This is Flyweight built into the JVM.
V8 engine uses "shapes" (hidden classes) as flyweights — objects with the same property layout share the same hidden class, drastically reducing per-object overhead.
Java caches Integer objects from -128 to 127. Python caches small integers. Both are Flyweight — frequently used values share a single object instead of being re-created.
Game engines like Unity and Unreal share meshes, textures, and materials via asset references. Multiple game objects can reference the same mesh/texture asset — that asset is the flyweight.