TypeScript Visitor Pattern Example

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.
  1. TypeScript Singleton Pattern Example
  2. TypeScript Factory Design Pattern with Example
  3. TypeScript Abstract Factory Pattern Example
  4. TypeScript Builder Pattern Example
  5. 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.
  1. TypeScript Bridge Pattern Example
  2. TypeScript Adapter Pattern Example
  3. TypeScript Decorator Pattern Example
  4. TypeScript Composite Pattern Example
  5. TypeScript Flyweight Design Pattern Example
  6. TypeScript Facade Pattern Example
  7. TypeScript Proxy Pattern Example

3. Behavioral Design Patterns

Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.
  1. TypeScript Command Pattern Example
  2. TypeScript Chain of Responsibility Pattern Example
  3. TypeScript Visitor Pattern Example
  4. TypeScript Template Method Pattern Example
  5. TypeScript Strategy Pattern Example
  6. TypeScript State Pattern Example
  7. TypeScript Observer Pattern Example
  8. TypeScript Memento Pattern Example
  9. TypeScript Mediator Pattern Example
  10. TypeScript Iterator Pattern Example
  11. TypeScript Interpreter Design Pattern Example