STRUCTURAL PATTERNS / OBJECT DESIGN BRIEF

Flyweight pattern

The Flyweight pattern reduces memory by sharing the common, immutable part of many similar objects.

AdvancedPhase 05 / Topic 6 of 7ResponsibilitiesCollaborationsExtensibility
01

Overview

The Flyweight pattern reduces memory by sharing the common, immutable part of many similar objects. It splits object state into intrinsic state (shared, like a tree type's texture and mesh) and extrinsic state (unique per instance, like each tree's position). A factory caches flyweights so each intrinsic combination exists once.

Flyweight matters when you have huge numbers of objects: characters in a text editor, trees or bullets in a game, map markers, or tokens in a compiler. Java's Integer cache and string interning are everyday flyweights.

Font glyphs in a document

A book has millions of letters, but the shape of the letter 'e' in a given font is stored once. Each occurrence only records where it appears.

02

When to use it

  • Millions of similar objects consume too much memory.
  • Most object state can be shared and made immutable.
  • Identity of individual objects does not matter for the shared part.
03

Where it shows up in interviews

Memory optimization

Recognize it when: huge counts of similar objects.

  • Design a text editor
  • Design a game with a forest of trees
  • Design a map with millions of markers
04

Where it is used in real software

Java Integer.valueOf and String.intern

Small integers (-128 to 127) and interned strings are shared instances.

Game engines

GPU instancing renders thousands of copies of one mesh with per-instance transforms.

Text editors

Glyph caches share font rendering data across characters.

05

Key terms

Intrinsic state
Shared, immutable data stored in the flyweight.
Extrinsic state
Context-specific data passed in or stored separately.
Flyweight factory
Returns cached instances for a key.
Interning
Keeping one canonical copy of equal values.
06

How it works, step by step

  1. 1
    Measure memory

    Confirm object count is the problem.

  2. 2
    Split state

    Intrinsic (shared) vs extrinsic (unique).

  3. 3
    Make intrinsic state immutable

    Safe to share.

  4. 4
    Create a factory with a cache

    Key by intrinsic attributes.

  5. 5
    Store extrinsic state separately

    In lightweight instance records.

07

Forest of one million trees

Each tree type has a 50 KB texture; 3 types

Step 1 / 2
DesignTexture memoryPer-tree memory
Texture per tree1,000,000 x 50 KB = 50 GBLarge
Flyweight TreeType shared3 x 50 KB = 150 KBx, y, type reference (~24 bytes)

NOWDesign: Texture per tree | Texture memory: 1,000,000 x 50 KB = 50 GB | Per-tree memory: Large

Sharing intrinsic state turns an impossible memory footprint into a trivial one.

08

Implementation

class TreeType { // flyweight: intrinsic, immutable  constructor(readonly name: string, readonly color: string, readonly texture: Uint8Array) {}  draw(x: number, y: number) { return `${this.name}@${x},${y}`; }} class TreeTypeFactory {  private static cache = new Map<string, TreeType>();  static get(name: string, color: string) {    const key = `${name}:${color}`;    let type = this.cache.get(key);    if (!type) {      type = new TreeType(name, color, new Uint8Array(50_000)); // loaded once      this.cache.set(key, type);    }    return type;  }  static count() { return this.cache.size; }} class Tree { // extrinsic state only  constructor(readonly x: number, readonly y: number, readonly type: TreeType) {}} const forest = Array.from({ length: 100_000 }, (_, i) =>  new Tree(i % 1000, Math.floor(i / 1000), TreeTypeFactory.get(i % 2 ? "oak" : "pine", "green")));TreeTypeFactory.count(); // 2
09

Complexity and performance

MemoryO(distinct intrinsic) + O(n) small records

vs O(n) large objects.

LookupO(1) hash

Factory cache.

10

Trade-offs

Memory vs complexity

Saves memory but splits state and complicates code; only use when object counts are huge.

Thread safety

Shared factories need concurrent maps; flyweights must be immutable.

11

Variants and related techniques

Interning

Canonicalize equal values (strings, enums).

Object pools

Reuse mutable objects over time; different from sharing immutable ones.

12

Common mistakes

  • Mutable flyweights.

    Fix: Shared state must be immutable, or one change affects every user.

  • Premature use.

    Fix: Measure memory first; modern JVMs handle millions of small objects.

13

Interview questions

Intrinsic vs extrinsic state?

Intrinsic state is shared and context-independent (the letter shape, the tree texture) and lives in the flyweight. Extrinsic state varies per use (position, color override) and is stored or passed separately.

How would you store characters in a text editor efficiently?

Share glyph flyweights for each (character, font, size) combination and store only positions and references per character, often combined with a piece table or rope for the text itself.

14

Practice problems

ProblemDifficultyWhat it trains
Forest renderer with shared tree typesMediumState split.
Map with millions of markers and shared iconsMediumFactory cache.