← Back to scenarios
ScenarioCatalog DB

Shape visitor

Apply rendering or measurement operations to shapes without changing the shape classes.

Problem

A graphics system needs to render and measure multiple shape types while keeping those operations separate from the stable shape hierarchy.

Related patterns

Implementations

Visitor

TypeScriptApplication

TypeScript shape operation visitors

Moves rendering and measurement operations into visitors so shape classes remain stable when new operations are introduced.

TypeScript
interface ShapeVisitor<Result> {
  visitCircle(circle: Circle): Result;
  visitRectangle(rectangle: Rectangle): Result;
}

interface Shape {
  accept<Result>(visitor: ShapeVisitor<Result>): Result;
}

class Circle implements Shape {
  constructor(readonly radius: number) {}

  accept<Result>(visitor: ShapeVisitor<Result>) {
    return visitor.visitCircle(this);
  }
}

class Rectangle implements Shape {
  constructor(
    readonly width: number,
    readonly height: number,
  ) {}

  accept<Result>(visitor: ShapeVisitor<Result>) {
    return visitor.visitRectangle(this);
  }
}

class AreaVisitor implements ShapeVisitor<number> {
  visitCircle(circle: Circle) {
    return Math.PI * circle.radius ** 2;
  }

  visitRectangle(rectangle: Rectangle) {
    return rectangle.width * rectangle.height;
  }
}

Associated technologies