introduce
Decorators offer more flexible alternatives than inheritance. Decorators use objects used to wrap the same interface, which not only allows you to add behavior to methods, but also set the methods to original object calls (such as the decorator's constructor).
Decorators are used to add new functions through the form of overloaded methods. This mode can add its own behavior before or after the decorator to achieve a specific purpose.
text
So what are the benefits of Decorator Mode? As mentioned earlier, the decorator is an alternative to achieving inheritance. When the script is running, adding behavior to the subclass affects all instances of the original class, but the decorator does not. Instead it can add new behavior to different objects. The following code looks like:
The code copy is as follows:
//Class (function) that needs decoration (function)
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());
Below 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 lower object.
The code copy is as follows:
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();
Let’s take another thorough example:
The code copy is as follows:
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(); // Step 7: First execute the prototype (this is Angel) decorate method
console.log('Put on some red balls'); // Step 8 output red
// Use these 2 steps as the decorate method of RedBalls
}
};
tree.BlueBalls = function () {
this.decorate = function () {
this.BlueBalls.prototype.decorate(); // Step 1: First execute the prototype's decorate method, that is, tree.decorate()
console.log('Add blue balls'); // Step 2 output blue
// Use these 2 steps as the BlueBalls decorate method
}
};
tree.Angel = function () {
this.decorate = function () {
this.Angel.prototype.decorate(); // Step 4: First execute the prototype (this is BlueBalls) decorate method
console.log('An angel on the top'); // Step 5 output angel
// Use these 2 steps as Angel's decorate method
}
};
tree = tree.getDecorator('BlueBalls'); // Step 3: Assign the BlueBalls object to tree, and the getDecorator in the parent prototype is still available
tree = tree.getDecorator('Angel'); // Step 6: Assign the Angel object to tree. At this time, the getDecorator in the parent prototype of the parent prototype is still available
tree = tree.getDecorator('RedBalls'); // Step 9: Assign the RedBalls object to tree
tree.decorate(); // Step 10: Execute the decorate method of the RedBalls object
Summarize
The decorator pattern is a way to dynamically add more functions to existing functions. Each function to be decorated is placed in a separate function, and then use this function to wrap the existing function object to be decorated. Therefore, when special behavior needs to be performed, the calling code can selectively and sequentially use the decorating function to wrap the object as needed. The advantage is that it distinguishes the core responsibilities of the class (function) from the decorative function.