structural

Flyweight

Use sharing to support large numbers of fine-grained objects efficiently by separating shared intrinsic state from per-object extrinsic state.

Problem

structural

A system creates a large number of similar objects, but storing all of their state separately uses too much memory.

Integration notes

Flyweight is useful when thousands or millions of similar objects need to be represented efficiently, such as trees, glyphs, tiles, or UI tokens.

Tradeoffs

  • Adds complexity because state must be split into shared and unshared parts
  • Can be harder to understand when many objects depend on an external context

Languages

typescript, java, python, angular, react, react-native, csharp, dotnet

Platforms

Web, Backend, Mobile, UI kits, Cross-platform systems

Variants

Scenarios

Tree rendering flyweight

A forest renderer shares tree type data across many individual tree instances to minimize memory usage.

Language examples

Core languages

Frameworks and libraries

Tree rendering flyweighttypescript

The tree flyweight shares tree type data like color and texture, while each tree instance stores only its position in the forest.

TypeScript
interface TreeType {
  render(x: number, y: number): string;
}


class SharedTreeType implements TreeType {
  constructor(
    private name: string,
    private color: string,
    private texture: string,
  ) {}


  render(x: number, y: number): string {
    return `Tree ${this.name} at (${x}, ${y}) with ${this.color} leaves and ${this.texture} texture`;
  }
}


class TreeTypeFactory {
  private types = new Map<string, SharedTreeType>();


  getTreeType(name: string, color: string, texture: string): SharedTreeType {
    const key = `${name}|${color}|${texture}`;
    if (!this.types.has(key)) {
      this.types.set(key, new SharedTreeType(name, color, texture));
    }


    return this.types.get(key)!;
  }
}


class Tree {
  constructor(
    private x: number,
    private y: number,
    private type: TreeType,
  ) {}


  draw(): string {
    return this.type.render(this.x, this.y);
  }
}


const factory = new TreeTypeFactory();
const pine = factory.getTreeType("Pine", "green", "rough");
const oak = factory.getTreeType("Oak", "dark green", "bark");


const forest = [
  new Tree(10, 20, pine),
  new Tree(15, 22, pine),
  new Tree(30, 40, oak),
];


console.log(forest.map((tree) => tree.draw()).join("\n"));

Real-world examples

  • Forest rendering: Games and simulations often reuse one tree model or texture definition across thousands of placed trees.
  • Text glyph caching: Text renderers commonly share glyph shapes or font data while each character instance stores only placement details.
  • Tile maps: Strategy games and editors often reuse terrain definitions and store only tile position and runtime state per cell.