Chain of Responsibility

Posted by Dustin Boston .


CAUTION

Construction Area
Watch out for:

  • Broken code
  • No comments
  • Partial examples
  • Missing tests

Source Code Listing

code.ts

type Handler = {
  handleRequest(request: string): void; // Pass the request data
  setSuccessor(successor: Handler | undefined): void;
};

class AbstractHandler implements Handler {
  protected successor: Handler | undefined = undefined;

  constructor(protected kind: string) {}

  setSuccessor(successor: Handler | undefined): void {
    this.successor = successor;
  }

  handleRequest(request: string): void {
    if (this.canHandle(request)) {
      this.handle(request);
    } else if (this.successor !== undefined) {
      this.successor.handleRequest(request);
    }
  }

  protected canHandle(_request: string): boolean {
    return true; // Default implementation, subclasses can override
  }

  protected handle(_request: string): void {
    // Subclasses should implement this to define their handling logic
  }
}

class ConcreteHandler1 extends AbstractHandler {
  protected handle(request: string): void {
    console.log(`${this.kind} handled request: ${request}`);
  }
}

class ConcreteHandler2 extends AbstractHandler {
  protected canHandle(request: string): boolean {
    return request.startsWith("prefix_"); // Example condition
  }

  protected handle(request: string): void {
    console.log(`${this.kind} handled request: ${request}`);
  }
}

const client = {
  run(): void {
    const handler1 = new ConcreteHandler1("foo");
    const handler2 = new ConcreteHandler2("bar");

    handler2.setSuccessor(handler1); // Set the chain

    handler2.handleRequest("some_request"); // Will be handled by handler1
    handler2.handleRequest("prefix_another_request"); // Will be handled by handler2
  },
};

client.run();