Dynamically add alternate processing to objects. 动态地为一个对象添加一些额外的职责,相比生成子类的形式更加灵活。
- 与 Mixin 类似,它们可以被认为是另一个可行的对象子类化的替代方案。装饰本身对于原类的基本功能来说不是必要的,所以它能够被动态添加至系统现有类的能力。
- 装饰者,可以修改现有的系统,在系统中为对象添加额外的功能之时,不需要大量修改它们的底层代码。这种模式一般会在需要大量不同类型的对象功能的时候使用。因为创建一个几百种不同类型对象的构造函数是一件可怕的事情。
- Instance decorator / Class decorator
动机:希望为对象而不是整个类添加一些功能。
适用性:
- 不影响其他类的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能够采用生成子类的方法进行扩充的时候。
代码结构:
标准的 Java 式 Decorator
interface Vehicle {
run();
}
class Bus extends Vehicle {
public run() {};
}
class Car extends Vehicle {
public run() {};
}
class EngineDecorator implements Vehicle {
private vehicle: Vehicle;
constructor(vehicle: Vehicle, engineType: string) {
this.vehicle = vehicle;
this.setEngine(engineType);
}
setEngine(engineType: string) {
this.vehicle.engineType = engineType;
}
getEngineSpeed() {}
run() {
this.engineSpeed = this.getEngineSpeed();
this.vehicle.run();
}
}
const myBus = new EngineDecorator(new Bus(), '6g');
const myCar = new EngineDecorator(new Car(), '4g');
function addPrototypeChain(obj) {
obj.prototype.getPrototypeChain = () => {};
obj.prototype.setPrototypeChain = () => {};
return obj;
}
function addDelayExecution(obj) {
obj.delayExecution = () => {};
}
// ES6 Method Decorator
// ES6 Class Decorator
@lazyLoad('image')
class Calendar extends Component {
@deprecated('warning');
doStuff() {
// do stuff
}
}
实现思路:
- 满足和装饰的接口的「一致性」。因而
ConcreteDecorator
需要一个父类来保证这种接口的一致性。 - 改变对象的「外壳」而非「内核」,内核交给
Strategy
模式来处理。
举例:
- Java I / O 中,使用
InputStream
作为实例,而FileInputStream
作为一个Decorator
为InputStream
装饰(扩展)功能,使之具有额外处理文件流的能力。
效果:
- 比静态继承更加灵活。
- 避免在层次结构高层的类有太多的职责。
- Decorator 是透明包装。
- 有许多小对象。
类比:
- 和 Adapter 不同的是,它强调「扩展」能力,而非「适配」接口。