This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Decorator pattern

Now let’s look at the decorator pattern. First of all, what is the decorator pattern?

The decorator pattern is to change or extend the original class without invading it.

Let’s look at this example:

// Phone.ts
export default class Phone {
  getPrice() {
    return 1000;
  };
  call() {
    console.log('calling'); }}Copy the code

Next, we want to add a case to this phone, we can add a decorator.

A decorator is simply a function.

// addCase.ts
import Phone from './Phone';

// Add a phone case
export default function addCase(P: typeof Phone) {
  return class extends P {
    getPrice() {
      return super.getPrice() + 50; }}}Copy the code

So how do we use this decorator? First we will introduce the decorator again, modify the following, so that we can add a phone case to the phone

// Phone.ts

import addCase from './addCase';

class Phone {
  getPrice() {
    return 1000;
  };
  call() {
    console.log('calling'); }}export default addCase(Phone);
Copy the code

When we use it, getPrice returns 1050.

// index.ts
import Phone from './Phone';

let p = new Phone();

console.log(p.getPrice()); / / 1050
Copy the code

Instead of calling the decorator directly, we can use the @ operator in front of the class and label the class as the default export. The same effect can be achieved.

// Phone.ts

import addCase from './addCase';

@addCase
export default class Phone {
  getPrice() {
    return 1000;
  };
  call() {
    console.log('calling'); }}Copy the code

Problem: Understand the decorator pattern and calculate the following results

The answer:

20

Resolution:

Decorator mode dynamically adds functionality to an object during program runtime without changing the object itself.

ES6 starts to identify decorators with @, @decorator. The animalDecorator class in the title is a class decorator that is called at run time as a function, with the constructor of the class as its only argument.

Generics knowledge is used in the decorator (which we’ll cover in more detail in the generics section).

To better understand the decorator, let’s look at the TSC compiled core code

const animalDecorator = (constructor) = > {
    return class extends constructor {
        constructor() {
            super(... arguments);this.age = 20; }}; };let Animal = class Animal {
    constructor(age) {
        this.age = age; }}; Animal = __decorate([ animalDecorator ], Animal);new Animal(10).age;
Copy the code

The class decorator animalDecorator returns an anonymous class named anonymous class A for short below. Class A inherits from the constructor of class Animal. At runtime, the constructor of class Animal is executed first, and the constructor of class A is executed, thus fulfilling the purpose of decorator. So the answer is 20.