In depth understanding of JavaScript series (29) : details of decorator patterns for design patterns

  • 2020-05-10 17:41:16
  • OfStack

introduce

Decorators offer a more flexible alternative to inheritance. Decorators use objects that wrap the same interface, allowing you not only to add behavior to methods, but also to set methods to be called by the original object (such as decorators' constructors).

Decorators are used to add new functionality in the form of overloaded methods, which can add their own behavior before or after the decorator to achieve a specific purpose.

The body of the

So what are the benefits of decorator mode? As mentioned earlier, decorator is an alternative to implementing inheritance. When the script runs, adding behavior to subclasses affects all instances of the original class, but decorators do not. Instead, it can add new behavior to different objects. The following code is shown:


// Class (function) to decorate
function Macbook() {
    this.cost = function () {
        return 1000;
    };
} function Memory(macbook) {
    this.cost = function () {
        return macbook.cost() + 75;
    };
} function BlurayDrive(macbook) {
    this.cost = function () {
        return macbook.cost() + 300;
    };
}
function Insurance(macbook) {
    this.cost = function () {
        return macbook.cost() + 250;
    };
}
// usage
var myMacbook = new Insurance(new BlurayDrive(new Memory(new Macbook())));
console.log(myMacbook.cost());

Here is another example. When we call performTask on the decorator object, it not only has some decorator behavior, but also calls the performTask function of the underlying object.


function ConcreteClass() {
    this.performTask = function () {
        this.preTask();
        console.log('doing something');
        this.postTask();
    };
} function AbstractDecorator(decorated) {
    this.performTask = function () {
        decorated.performTask();
    };
} function ConcreteDecoratorClass(decorated) {
    this.base = AbstractDecorator;
    this.base(decorated);     decorated.preTask = function () {
        console.log('pre-calling..');
    };     decorated.postTask = function () {
        console.log('post-calling..');
    }; } var concrete = new ConcreteClass();
var decorator1 = new ConcreteDecoratorClass(concrete);
var decorator2 = new ConcreteDecoratorClass(decorator1);
decorator2.performTask();

Here's another thorough example:


var tree = {};
tree.decorate = function () {
    console.log('Make sure the tree won\'t fall');
}; tree.getDecorator = function (deco) {
    tree[deco].prototype = this;
    return new tree[deco];
}; tree.RedBalls = function () {
    this.decorate = function () {
        this.RedBalls.prototype.decorate(); // The first 7 Step: execute the prototype first (in this case Angel A) decorate methods
        console.log('Put on some red balls'); // The first 8 step Then the output red
        // Will this 2 Step as RedBalls the decorate methods
    }
}; tree.BlueBalls = function () {
    this.decorate = function () {
        this.BlueBalls.prototype.decorate(); // The first 1 Step: execute the prototype first decorate The method, that is tree.decorate()
        console.log('Add blue balls'); // The first 2 step Then the output blue
        // Will this 2 Step as BlueBalls the decorate methods
    }
}; tree.Angel = function () {
    this.decorate = function () {
        this.Angel.prototype.decorate(); // The first 4 Step: execute the prototype first (in this case BlueBalls A) decorate methods
        console.log('An angel on the top'); // The first 5 step Then the output angel
        // Will this 2 Step as Angel the decorate methods
    }
}; tree = tree.getDecorator('BlueBalls'); // The first 3 Step: BlueBalls The object is assigned to tree "In the parent archetype getDecorator Still available
tree = tree.getDecorator('Angel'); // The first 6 Step: Angel The object is assigned to tree Of the parent archetype getDecorator Still available
tree = tree.getDecorator('RedBalls'); // The first 9 Step: RedBalls The object is assigned to tree tree.decorate(); // The first 10 Step: perform RedBalls The object's decorate methods

conclusion

Decorator pattern is dynamically adding more functionality to an existing function of 1, the function of the decoration of the each to put in a separate function, and then packed in the function to decoration function object, therefore, when you need to perform special behavior, the calling code can selectively according to need, in order to use objects decorative function to packaging. The advantage is that it separates the core responsibilities of a class (function) from the decorative functions.


Related articles: