装饰器模式

1. 装饰器模式.

装饰者模式(Decorator): 在不改变原对象的基础上,对其进行包装扩展,以满足更复杂的需求.

1.1 为什么使用装饰器模式

一般情况下, 我们为了扩展一个类经常用到继承的方式实现,由于继承为类引入了静态体征,并且随着功能的增多,子类会越来越大.

这时我们可以用到装饰器模式,给子类进行扩展,装饰器和被装饰类可以独立发展,不会相互耦合,装饰模式时继承模式的一个替代模式,装饰模式可以动态扩展一个实现类的功能.

  • 场景一
// Student实例类
class Student{
    constructor(name,sex,hobby){
        this.name = name;
        this.sex = sex
        this.hobby = hobby
    }
    showName(){
        console.log(this.name);
    }
}
  // 实例使用
const zhangsan = new Student('张三','男',"打篮球"),
      lisi = new Student('李四', '男', "看书"),
      wangwu = new  Student('王五', '男', "学习");
// 现在我们需要对lisi实例(或个别实例), 进行添加新的属性的扩展
// 很显然此时不能直接扩展到Student类上,不然会影响到其他实例
//如果继承,那么需要重新实例化新的,不必要而且浪费
//此时我们可以使用装饰器模式在以有的实例上稍做装饰就能满足需求
 function Decorator(instance,options){
     for(let [key,val] of Object.entries(options)){
         // 如果不存在对应的属性就给目标对象添加对应的属性值
         if (!Reflect.get(instance, key)) {
             Reflect.defineProperty(instance, key, {
                 value: val,
             })
         }else{
             console.error(`target Object an existing ${key} attribute`)
         }
     }
    }
// 利用装饰器函数给lisi实例添加一个age属性,和sayAge方法
Decorator(lisi, { age: 12,sayAge(){
    console.log(this.age);
}})
lisi.sayAge()// 12
lisi.sayName()//李四
 let arr = [ 4,324,4,43,43];
// 假设我们要给数组的实例arr添加一个方法,显然我们如果利用原型继承给Array的原型添加方法是不合适的
// 此时我们也可以使用装饰器模式
Decorator(arr,{
    max(){
        return  Math.max.call(null, ...this)
    }
})  
arr.max();// 324            

更复杂的装饰器模式还可以继续抽象为类,实现对对象的扩展.

总结:装饰器模式是一种常见的结构型模式,我们可以以一个基础对象为基础,来给它加上若干个装饰对齐以扩展其功能,装饰模式也是一种更灵活的继承方案,对对象进行多需要的扩展而不需要重新继承构造出新的实例.

推荐阅读更多精彩内容