Flyweight only becomes compelling when there are many fine-grained objects and shared state can be separated safely.
Use sharing to support large numbers of fine-grained objects efficiently.
What the pattern is trying to do
Use sharing to support large numbers of fine-grained objects efficiently.
What force creates the need
The system creates many similar small objects, and memory pressure grows because shared state is duplicated repeatedly.
How the pattern responds
Extract common intrinsic state into shared flyweights and keep varying extrinsic state outside the shared objects.
How the moving parts fit together
A flyweight factory manages shared instances keyed by intrinsic state, while callers provide extrinsic context at use time.
Java example in the Order Management domain
package org.javaomnibus.ecommerce.gof.structural;
public record CurrencyDisplayStyle(String symbol, String localeCode) {}
public final class CurrencyDisplayStyleFactory {
private final java.util.Map cache = new java.util.HashMap<>();
public CurrencyDisplayStyle forCode(String currencyCode) {
return cache.computeIfAbsent(currencyCode, code -> switch (code) {
case "USD" -> new CurrencyDisplayStyle("$", "en-US");
case "EUR" -> new CurrencyDisplayStyle("EUR", "de-DE");
default -> new CurrencyDisplayStyle(code, "en-US");
});
}
}
Step by step
- Shared style metadata is cached by currency code.
- Callers reuse intrinsic display state instead of recreating it repeatedly.
- Flyweight only helps if the sharing opportunity is real and object counts are high enough to matter.
- The separation between intrinsic and extrinsic state is the core design move.
Where this pattern helps
- When very large numbers of similar objects are created
- When shared immutable state can be separated cleanly from request-specific context
When a simpler design is better
- When memory pressure is not actually a problem
- When state cannot be split safely into shared and external parts
What this pattern costs
- Introduces indirection and state-splitting complexity
- Can make code harder to understand if applied without real performance pressure
How this fits today
Flyweight is less common than Adapter or Facade in everyday Java, but it still matters in rendering systems, large catalogs, parsers, caches, and memory-sensitive workloads.
Where teams get it wrong
Adding flyweight-style caching to ordinary objects with low creation volume creates complexity long before it creates measurable value.