装饰者模式
动态的给一个对象扩展一些额外的功能,比如在调用对象之前或者之后增加新的功能,还不影响原对象本有的功能,就像是给对象增加了一些装饰。
装饰模式又称为包装模式,对象被包装后,还可以继续包装添加新的功能,从而扩展对象的功能,通过装饰模式可以使系统更具有弹性,且其遵循了面向对象原则:对外开放,对修改关闭。
普通JS实现装饰模式
var House = {
style : function() {
console.log('普通房子')
}
}
var treeDecorator = function (){
console.log('周围有绿化')
}
let style = House.style;
House.style = function() {
style();
treeDecorator()
};
House.style();
其中,重写style 方法,将原来的style和treeDecorator重新包装,然后赋值给House对象的style属性,增加原有style的功能。
基于TypeScript 的装饰器的功能
TypeScript 中的装饰器使用 @expression 这种形式,expression 求值后为一个函数,它在运行时被调用,被装饰的声明信息会被做为参数传入。
let template;
function checkCar(target, key, descriptor) {
console.log('before checking');
template = target;
}
function CloseCar(target, key, descriptor){
console.log('close car');
template = target;
}
class CarModel {
@checkCar
driver() {
console.log('moving')
}
@CloseCar
stop() {
console.log('stop...')
}
}
const car = new CarModel();
car.driver();
但是需要注意,需要开启对装饰器的支持,
命令行编译文件:
tsc --target ES5 --experimentalDecorators demo.ts
通过增加配置文件
{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true } }
装饰器使用
- 在需要装饰的类,方法或属性上增加 @符号+ 方法
- 支持多个装饰,执行顺序将按 从下到上 依此执行
- 可支持装饰器:类、方法、属性、访问符装饰器,参数装饰器
- 若都存在以上几种装饰器,那么这些访问器的顺序是,属性装饰器 -> 访问符装饰器 -> 方法装饰器 -> 参数装饰器 -> 类装饰器。
优点
- 比继承灵活,动态对对象扩展,即插即用
- 通过使用不同的装饰类及这些装饰类的排列组合,可以实现不同效果
- 完全遵守开闭原则
应用场景
- 当需要给现有类增加附加职责,而又不能采用生成子类的方法进行扩充时
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多功能时
- 当对象的功能要求可以动态添加,也可以再动态地撤销时