+TypeScript example
Nodes connect their concrete kind to the visitor; visitors own operations such as rendering and counting. A new operation can then be added without another method in every node class.
interface IDocNode { accept(visitor: IVisitor): void; }
// Collect the element-specific parts of one operation in its visitor.
interface IVisitor {
visitText(node: TextNode): void;
visitImage(node: ImageNode): void;
}
// The node selects its matching visitor method without implementing the operation itself.
class TextNode implements IDocNode {
constructor(readonly text: string) {}
accept(visitor: IVisitor): void { visitor.visitText(this); }
}
class ImageNode implements IDocNode {
constructor(readonly caption: string) {}
accept(visitor: IVisitor): void { visitor.visitImage(this); }
}
class TextVisitor implements IVisitor {
readonly lines: string[] = [];
visitText(node: TextNode): void { this.lines.push(node.text); }
visitImage(node: ImageNode): void { this.lines.push("[image: " + node.caption + "]"); }
}
class CountVisitor implements IVisitor {
texts = 0;
images = 0;
visitText(node: TextNode): void { this.texts++; }
visitImage(node: ImageNode): void { this.images++; }
}
const nodes: IDocNode[] = [new TextNode("hello"), new ImageNode("cover"), new TextNode("world")];
const render = new TextVisitor();
const count = new CountVisitor();
for (const node of nodes) { node.accept(render); node.accept(count); }
for (const line of render.lines) console.log(line);
console.log("text nodes: " + count.texts);
console.log("image nodes: " + count.images);
hello
[image: cover]
world
text nodes: 2
image nodes: 1
TypeScript overload signatures share a single implementation. This version gives the C# Visit(TextNode) and Visit(ImageNode) operations distinct names, visitText and visitImage, called by the matching accept().