Structural · DWG NO. 014

Flyweight

Share the heavy, unchanging parts of many similar objects instead of duplicating them per instance.

TypeStructural
ScopeMany similar objects
ComplexityMedium
Common inText/glyph rendering, game particles, map tiles

A million near-identical objects, each paying for its own copy of shared data

Rendering a page of text as one object per character, each holding its own copy of the font's full glyph bitmap, wastes enormous memory — most of that data (the glyph shape) is identical across every 'a' on the page. Only the position differs per character.

Split shared state from unique state

The unchanging, shareable part (intrinsic state — the glyph shape) lives in one flyweight object, reused by every occurrence. The part that varies per instance (extrinsic state — x/y position) is passed in from the outside at use time instead of stored on the flyweight.

GlyphFactoryGlyph "a" (shared)Glyph "b" (shared)pos (12,4)pos (40,4)

Sharing glyph shapes across many character instances

The factory caches one flyweight per character; a million on-screen letters reuse just 26 shared glyph objects.

glyph-flyweight.js
class Glyph {
  constructor(char) {
    this.char = char;
    this.bitmap = `<expensive bitmap data for '${char}'>`; // shared, loaded once
  }
  drawAt(x, y) {
    console.log(`drawing '${this.char}' at (${x}, ${y})`);
  }
}

class GlyphFactory {
  static #cache = new Map();
  static get(char) {
    if (!GlyphFactory.#cache.has(char)) {
      GlyphFactory.#cache.set(char, new Glyph(char));
    }
    return GlyphFactory.#cache.get(char);
  }
}

function renderText(text) {
  let x = 0;
  for (const char of text) {
    GlyphFactory.get(char).drawAt(x, 0); // extrinsic position, passed in
    x += 8;
  }
}

renderText("hello hello"); // only 5 distinct Glyph objects created ('h','e','l','o',' ')

Trade-offs