The Problem
Large collections often repeat the same immutable data many times. A cart, a catalog index, or an inventory snapshot might contain thousands of references to the same SKU metadata. If every item owns a full copy, memory usage grows with needless duplication.
The Solution
Flyweight extracts the shared intrinsic state into a reusable object and keeps changing extrinsic state outside of it. In Go, a cache or factory typically owns the shared flyweights, while callers keep their per-instance quantities, locations, or timestamps separately.
Structure
- Flyweight:
ProductMetadataholds shared immutable SKU data. - Flyweight factory:
MetadataFactoryreturns cached flyweights by SKU. - Context object:
CartLinekeeps changing per-line values such as quantity and warehouse. - Client: Reuses the same flyweight across multiple contexts.
Implementation
This example shares catalog metadata for repeated SKUs across multiple cart lines. Each line keeps its own quantity and warehouse, while the expensive descriptive fields are reused through a factory-managed cache.
package main
type ProductMetadata struct {
SKU string
Name string
Category string
} Best Practices
- Keep flyweights immutable or treat them as effectively read-only once cached.
- Separate intrinsic shared state from extrinsic per-instance state clearly.
- Measure first. Flyweight is a performance pattern and only matters when repetition is actually large enough.
- Hide caching behind a factory so callers do not manage reuse manually.
- Avoid Flyweight if shared state becomes difficult to reason about or accidentally mutable.
When to Use
- You have many objects that repeat the same immutable data.
- Memory pressure or cache efficiency matters.
- Shared metadata can be safely reused across many contexts.
When NOT to Use
- The objects are few enough that duplication is irrelevant.
- The supposedly shared state changes frequently.
- The performance optimization would complicate otherwise clear code.