+TypeScript 예제
노드는 자기 종류를 방문자에게 연결하고, 방문자는 출력·집계 같은 연산을 맡는다. 새 연산을 넣으려고 모든 노드 클래스에 메서드를 늘리지 않도록 나눈다.
interface IDocNode { accept(visitor: IVisitor): void; }
// 연산 하나에 필요한 요소별 처리를 방문자 한곳에 모은다.
interface IVisitor {
visitText(node: TextNode): void;
visitImage(node: ImageNode): void;
}
// 노드는 자기 종류에 맞는 방문자 메서드를 연결하며 연산 자체는 맡지 않는다.
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의 오버로드 선언은 타입 검사에 쓰이며 실제 함수 구현은 하나다. 여기서는 C#의 Visit(TextNode)·Visit(ImageNode)를 visitText·visitImage로 나누고 각 accept()에서 맞는 쪽을 부른다.