Decorator

Posted by Dustin Boston .


CAUTION

Construction Area
Watch out for:

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

Source Code Listing

code.ts

type Component = {
  add(key: string, value: any): void;
  get(): Record<string, any>;
  process(): void;
};

class ConcreteComponent implements Component {
  private props: Record<string, any> = {}; // Initialize props

  add(key: string, value: any): void {
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
    this.props[key] = value;
  }

  get(): Record<string, any> {
    return this.props;
  }

  process(): void {
    console.log("ConcreteComponent processing"); // Or any actual processing logic
  }
}

class Decorator implements Component {
  constructor(protected component: Component) {}

  add(key: string, value: any): void {
    this.component.add(key, value); // Delegate to the wrapped component
  }

  get(): Record<string, any> {
    return this.component.get(); // Delegate to the wrapped component
  }

  process(): void {
    this.component.process(); // Delegate to the wrapped component
  }
}

class ConcreteDecoratorA extends Decorator {
  process(): void {
    this.add("concreteDecoratorAProcess", true);
    super.process(); // Call the wrapped component's process after decoration
    console.log("ConcreteDecoratorA processing");
  }
}

class ConcreteDecoratorB extends Decorator {
  process(): void {
    this.add("concreteDecoratorBProcess", true);
    super.process(); // Call the wrapped component's process after decoration
    console.log("ConcreteDecoratorB processing");
  }
}

const example = {
  run(): void {
    const component: Component = new ConcreteDecoratorA(
      new ConcreteDecoratorB(new ConcreteComponent()),
    );
    component.process();
    console.log(component.get());
  },
};

example.run();