Patterns: composition · 3 MIN READ
Flyweight: share immutable intrinsic state
Separate reusable data from per-use context before optimizing memory.
Separate reusable data from per-use context before optimizing memory. Flyweight shares intrinsic state across many logical objects while callers supply extrinsic context. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.
Structural pattern · A MAP OF THE IDEA
- Catalog reuses one intrinsic glyph
- Placement supplies external position
- Many logical uses share immutable data
Useful when
- Many objects repeat sizable immutable data
- Extrinsic state can stay at each call site
Watch out
- Intern tables can retain unused data
- Mutable shared state breaks independence
Implementation & operation cost: Medium
Fit depends on the task
Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.
The design decision
Flyweight shares intrinsic state across many logical objects while callers supply extrinsic context. A glyph shape can be shared while its position belongs to each placement. The optimization is useful only when repeated retained data is large enough to matter.
A complete Go example
Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.
package main
import (
"fmt"
)
type Glyph struct{ shape string }
type Catalog struct{ glyphs map[string]*Glyph }
func (c *Catalog) Get(shape string) *Glyph {
if g := c.glyphs[shape]; g != nil {
return g
}
g := &Glyph{shape: shape}
c.glyphs[shape] = g
return g
}
type Placement struct {
Glyph *Glyph
X int
}
func main() {
c := Catalog{glyphs: make(map[string]*Glyph)}
a := Placement{Glyph: c.Get("G"), X: 1}
b := Placement{Glyph: c.Get("G"), X: 8}
fmt.Println(a.Glyph == b.Glyph, a.X, b.X)
}
// Output:
// true 1 8
Two placements share the same Glyph pointer but retain different positions. Treat shape as immutable after registration. The map is owned by one goroutine here; sharing Catalog concurrently would require synchronization or immutable publication.
Tradeoffs and the simpler alternative
An unbounded intern table can retain data forever and consume more memory than it saves. Measure object counts and retained size, bound the cache where necessary, and do not share mutable per-use fields such as selection or position inside the flyweight.
TAKE THIS WITH YOU
Shares immutable intrinsic state across many uses. An unbounded intern table can retain data forever and consume more memory than it saves. Measure object counts and retained size, bound the cache where necessary, and do not share mutable per-use fields such as selection or position inside the flyweight.
Check your understanding
Which statement best describes Flyweight: share immutable intrinsic state?
Go to the source
Progress stays in this browser. No account needed.