The decorator pattern is a code implementation that adds features to a function or class.
You can add new properties and methods to an existing object without modifying it.
There is a good example online that explains why the decorator pattern is needed. Suppose there is a bicycle business, which requires the bicycles in the store to be sold at different prices according to different accessories. The configuration items include headlights, taillights, bells, repair spanners, etc. You can choose one or several free combinations.
If you think about the combination results, there are dozens or hundreds of them. Every time you add a combination of accessories, it is horrible. Using classes means defining a type for each combination. This is clearly not scientific.
In this case, you can use decorators to solve the problem. Decorators are like combinations, defining a class for each accessory, such as a bike without accessories is a class, a headlight is a class, and taillights are a class. Taken together, these three form a class with headlights and taillights. If only taillight accessories are needed, combine the bicycle base class with the taillight class.
So you need two class objects here, one is Bicycle, which is the base class of a Bicycle, and the second is a BicycleDecotator class with a disassembled decorator
The bike base class contains the basic ride method and the base price, which is the price without any accessories.
// Base class
class Bicycle {
// Other methods
ride () {
console.log('Riding method');
}
getPrice() {
/ / 100
return 100; }}Copy the code
Create a decorator pattern base class that does nothing but accept an instance of Bicycle, implement its corresponding method, and call its method back.
class BicycleDecotator {
constructor(bicycle) {
this.bicycle = bicycle;
}
ride () {
return this.bicycle.ride();
}
getPrice() {
return this.bicycle.getPrice(); }}Copy the code
Once we have this base class, we can do whatever we want with the original Bicycle class. For example, I can create a decorator with headlights. The decorator has added 10 yuan to the original price.
class HeadLightDecorator extends BicycleDecorator {
constructor(bicycle) {
super(bicycle);
}
getPrice() {
return this.bicycle.getPrice() + 10; }}Copy the code
You can also create a decorator with taillights for $10 more for the same price.
class TailLightDecorator extends BicycleDecorator {
constructor(bicycle) {
super(bicycle);
}
getPrice() {
return this.bicycle.getPrice() + 20; }}Copy the code
Then, we can combine them freely. Bicycle is a basic bicycle, priced at 10 yuan.
let bicycle = new Bicycle(); // The original bike
console.log(bicycle.getPrice()); / / 100
Copy the code
By combining the basic and headlights, you create an instance of the HeadLightDecorator and pass in the bicycle instance.
const headbicycle = new HeadLightDecorator(bicycle);
console.log(headbicycle.getPrice()); / / 110
Copy the code
A bicycle with headlights and taillights is a bicycle with both headlights and taillights.
const tailbicycle = new TailLightDecorator(headbicycle);
console.log(tailbicycle.getPrice()); / / 120
Copy the code
The nice thing about this is that, let’s say we have 10 accessories, we only need to write 10 accessories decorators, and then we can make any bike with different accessories and calculate the price. With the subclass implementation, 10 widgets might have hundreds or even thousands of subclasses, which sounds scary.
Where decorator mode is used:
The decorator pattern should be used if you need to add features or responsibilities to a class, but the solution of subclassing from the class is not practical.
In our example, we did not modify the original Bicycle base class, so there are no side effects to the original code. We just added some features to the original. Therefore, if you want to add features to an object without changing the code that uses the object, you can use the decorator pattern.
Maybe you’ve been doing this for a long time, but you didn’t know it was a decorator. The common throttling and anti – shake front end is actually even decorator mode, but in JS we used to call it a higher order function.
function throttle(func, delay) {
const self = this;
let tid;
return function(. args) {
if (tid) return;
tid = setTimeout(() = >{ func.call(self, ... args); tid =null; }, delay); }}function debounce(func, delay) {
const self = this;
let tid;
return function(. args) {
if (tid) clearTimeout(tid);
tid = setTimeout(() = >{ func.call(self, ... args); tid =null; }, delay); }}Copy the code
[详 细]
- Rookie tutorial – Decorator mode
- Blog Park – Chen Chen JG