在 JavaScript 中,装饰器模式可以通过闭包和函数式编程技巧来实现。装饰器模式允许我们在不修改原始对象的基础上,动态地添加或修改功能。
以下是一个简单的装饰器模式的例子:
// 定义一个接口,用于装饰器
function Component() {
this.name = 'Component';
}
Component.prototype.getName = function() {
return this.name;
};
// 定义一个具体的组件
function ConcreteComponent() {
Component.call(this);
this.name = 'ConcreteComponent';
}
ConcreteComponent.prototype = Object.create(Component.prototype);
ConcreteComponent.prototype.constructor = ConcreteComponent;
// 定义一个装饰器基类
function Decorator(component) {
this._component = component;
}
Decorator.prototype.getName = function() {
return this._component.getName();
};
// 定义一个具体的装饰器
function ConcreteDecoratorA(component) {
Decorator.call(this, component);
}
ConcreteDecoratorA.prototype = Object.create(Decorator.prototype);
ConcreteDecoratorA.prototype.constructor = ConcreteDecoratorA;
ConcreteDecoratorA.prototype.getName = function() {
return '[' + this._component.getName() + '] ConcreteDecoratorA';
};
// 定义另一个具体的装饰器
function ConcreteDecoratorB(component) {
Decorator.call(this, component);
}
ConcreteDecoratorB.prototype = Object.create(Decorator.prototype);
ConcreteDecoratorB.prototype.constructor = ConcreteDecoratorB;
ConcreteDecoratorB.prototype.getName = function() {
return this._component.getName() + ' ConcreteDecoratorB';
};
// 使用装饰器
const concreteComponent = new ConcreteComponent();
console.log(concreteComponent.getName()); // 输出 "ConcreteComponent"
const decoratorA = new ConcreteDecoratorA(concreteComponent);
console.log(decoratorA.getName()); // 输出 "[ConcreteComponent] ConcreteDecoratorA"
const decoratorB = new ConcreteDecoratorB(decoratorA);
console.log(decoratorB.getName()); // 输出 "[ConcreteComponent] ConcreteDecoratorA ConcreteDecoratorB"
在这个例子中,我们首先定义了一个 Component
接口和两个实现了该接口的具体组件 ConcreteComponent
。然后,我们定义了一个装饰器基类 Decorator
和两个具体装饰器 ConcreteDecoratorA
和 ConcreteDecoratorB
。这些装饰器都接受一个组件作为参数,并在其 getName
方法中调用组件的 getName
方法,从而在不修改原始组件的基础上动态地添加了功能。
最后,我们创建了一个 ConcreteComponent
实例,并使用 ConcreteDecoratorA
和 ConcreteDecoratorB
对其进行装饰,然后打印出装饰后的组件名称。