Flyweight Pattern
Reduce memory usage by sharing reusable intrinsic state across many fine-grained objects and passing context-specific extrinsic state when operations are performed.

Concept Overview
The Flyweight pattern uses sharing to support large numbers of fine-grained objects efficiently. It separates intrinsic state, which is common and shareable, from extrinsic state, which varies by use context. The supplied infographic uses document characters: the symbol and font can be shared, while each occurrence receives its own x and y position. A factory manages the shared flyweights so repeated requests can reuse the same object.
1. The problem: too many similar objects consume memory
An application may create a large number of similar objects, such as characters in a document, map markers, particles or repeated UI glyphs. If every occurrence stores identical data independently, memory is used for many duplicate copies. The Flyweight pattern looks for state that can be shared safely and separates it from the data that changes for each occurrence.
2. Intrinsic state and extrinsic state
Intrinsic state is stable, context-independent information that can be shared. In the character example, the symbol and font are intrinsic. Extrinsic state depends on a particular occurrence or context. A character's x and y position are extrinsic because the same letter can appear at many locations. The client supplies extrinsic state when it asks the flyweight to perform an operation.
3. Participants and responsibilities
The Flyweight interface defines the operation that receives extrinsic state. A Concrete Flyweight stores intrinsic state. A Flyweight Factory creates or retrieves shared objects from a cache. The Client maintains context-specific state and requests flyweights from the factory. An unshared concrete flyweight can be used for cases where sharing is not applicable, but the supplied example focuses on shared characters.
4. Factory-managed sharing
The factory uses a stable key made from the intrinsic attributes, such as character symbol and font. When a caller requests a key already in the cache, the existing flyweight is returned. Otherwise the factory creates it and stores it for later reuse. The factory centralises sharing so clients do not accidentally construct duplicates. If the cache is accessed concurrently, its implementation must be thread-safe.
interface Glyph {
void draw(int x, int y); // extrinsic state
}
final class CharacterGlyph implements Glyph {
private final char symbol;
private final String font; // intrinsic state
CharacterGlyph(char symbol, String font) {
this.symbol = symbol;
this.font = font;
}
public void draw(int x, int y) {
System.out.printf("%c [%s] at (%d,%d)%n", symbol, font, x, y);
}
}
final class GlyphFactory {
private final Map<String, Glyph> cache = new HashMap<>();
Glyph get(char symbol, String font) {
String key = symbol + "|" + font;
return cache.computeIfAbsent(key,
ignored -> new CharacterGlyph(symbol, font));
}
}5. How the document client uses a flyweight
The document asks the factory for a glyph using the symbol and font. It then calls draw(x, y) for each occurrence. A document may contain many occurrences but only a small number of unique symbol-and-font combinations. The number of shared objects can therefore be much smaller than the number of positions in the document. The client must retain the per-occurrence coordinates because those values are not part of the shared flyweight.
6. Benefits, drawbacks and suitable workloads
Flyweight can reduce object count and memory consumption when many objects share substantial intrinsic state. It centralises shared data and can improve memory efficiency. The cost is more complex state management: developers must separate intrinsic from extrinsic data correctly, ensure shared state is immutable or safely accessed, and manage the factory cache. It is not useful when object counts are small or when little state can actually be shared.
Key Takeaways
- ✓Share intrinsic state and pass extrinsic state at the point of use.
- ✓A factory manages reuse so clients do not create duplicate flyweights.
- ✓Shared state should be immutable or protected against unsafe mutation.
- ✓Use Flyweight when memory pressure comes from many similar fine-grained objects.