In this article, we will learn how to use and implement the Visitor Pattern in TypeScript with an example.
Visitor is a behavioral design pattern that lets you separate algorithms from the objects on which they operate.
TypeScript Visitor Pattern Example
Let's create visitor.ts file and add the following code to it:
export interface Visitor {
visitConcreteElement1(concreteElement1: ConcreteElement1): void;
visitConcreteElement2(concreteElement2: ConcreteElement2): void;
}
export class ConcreteVisitor1 implements Visitor {
public visitConcreteElement1(concreteElement1: ConcreteElement1): void {
console.log("`visitConcreteElement1` of ConcreteVisitor1 is being called!");
}
public visitConcreteElement2(concreteElement2: ConcreteElement2): void {
console.log("`visitConcreteElement2` of ConcreteVisitor1 is being called!");
}
}
export class ConcreteVisitor2 implements Visitor {
public visitConcreteElement1(concreteElement1: ConcreteElement1): void {
console.log("`visitConcreteElement1` of ConcreteVisitor2 is being called!");
}
public visitConcreteElement2(concreteElement2: ConcreteElement2): void {
console.log("`visitConcreteElement2` of ConcreteVisitor2 is being called!");
}
}
export interface Element {
operate(visitor: Visitor): void;
}
export class ConcreteElement1 implements Element {
public operate(visitor: Visitor): void {
console.log("`operate` of ConcreteElement1 is being called!");
visitor.visitConcreteElement1(this);
}
}
export class ConcreteElement2 implements Element {
public operate(visitor: Visitor): void {
console.log("`operate` of ConcreteElement2 is being called!");
visitor.visitConcreteElement2(this);
}
}
export class Objs {
private elements: Element[] = [];
public attach(e: Element): void {
this.elements.push(e);
}
public detach(e: Element): void {
var index = this.elements.indexOf(e);
this.elements.splice(index, 1);
}
public operate(visitor: Visitor): void {
var i = 0,
max = this.elements.length;
for(; i < max; i += 1) {
this.elements[i].operate(visitor);
}
}
}
Usage
Let's create demo.ts file and add the following code to it:
import { Objs, ConcreteElement1, ConcreteElement2, ConcreteVisitor1, ConcreteVisitor2 } from "./visitor";
export function show() : void {
var objs: Objs = new Objs();
objs.attach(new ConcreteElement1());
objs.attach(new ConcreteElement2());
var v1: ConcreteVisitor1 = new ConcreteVisitor1(),
v2: ConcreteVisitor2 = new ConcreteVisitor2();
objs.operate(v1);
objs.operate(v2);
}
show();
Run:
- Compile the above code using the TypeScript compiler.
- Above code is compiled to plan JavaScript code
- Run Javascript code using node
design_patterns_in_typescript\visitor> tsc --target ES5 .\demo.ts
design_patterns_in_typescript\visitor> node .\demo.js
`operate` of ConcreteElement1 is being called!
`visitConcreteElement1` of ConcreteVisitor1 is being called!
`operate` of ConcreteElement2 is being called!
`visitConcreteElement2` of ConcreteVisitor1 is being called!
`operate` of ConcreteElement1 is being called!
`visitConcreteElement1` of ConcreteVisitor2 is being called!
`operate` of ConcreteElement2 is being called!
`visitConcreteElement2` of ConcreteVisitor2 is being called!
All TypeScript Design Patterns
1. Creational Design Patterns
Creational patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.
- TypeScript Singleton Pattern Example
- TypeScript Factory Design Pattern with Example
- TypeScript Abstract Factory Pattern Example
- TypeScript Builder Pattern Example
- TypeScript Prototype Pattern Example
2. Structural Design Patterns
Structural patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient.
- TypeScript Bridge Pattern Example
- TypeScript Adapter Pattern Example
- TypeScript Decorator Pattern Example
- TypeScript Composite Pattern Example
- TypeScript Flyweight Design Pattern Example
- TypeScript Facade Pattern Example
- TypeScript Proxy Pattern Example
3. Behavioral Design Patterns
Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.
- TypeScript Command Pattern Example
- TypeScript Chain of Responsibility Pattern Example
- TypeScript Visitor Pattern Example
- TypeScript Template Method Pattern Example
- TypeScript Strategy Pattern Example
- TypeScript State Pattern Example
- TypeScript Observer Pattern Example
- TypeScript Memento Pattern Example
- TypeScript Mediator Pattern Example
- TypeScript Iterator Pattern Example
- TypeScript Interpreter Design Pattern Example