JavaScript设计模式(五)-装饰器模式

JavaScript设计模式(五)-装饰器模式

(本来应该昨天更新的,但是生病了哦 ┭┮﹏┭┮。天气越来越冷,大家注意保暖)

创建型的三种模式已经介绍完了,今天介绍新的结构型哦~

装饰器模式(结构型)

圣诞节要到了,许多家庭会买一颗松树装上彩灯,一闪一闪亮晶晶然后摇身一变成了圣诞树。这里 的彩灯就是装饰器,他不会对松树原有的功能产生影响。(还是本来的树)

这种给对象动态地增加职责的方式称为装 饰器(decorator)模式。装饰器模式能够在不改 变对象自身的基础上,在程序运行期间给对象 动态地添加职责。

应用

当我们接手老代码,需要对它已有的功能做个拓展。

var horribleCode = function(){

  console.log(我是一堆你看不懂的老逻辑')

}

// 改成:

var horribleCode = function(){

  console.log('我是一堆你看不懂的老逻辑')

  console.log('我是新的逻辑')
}

这样做有很多的问题。直接去修改已有的函数体,违背了我们的“开放封闭原则”;往一个函数体里塞这么多逻辑,违背了我们的“单一职责原则”。

为了不被已有的业务逻辑干扰,将旧逻辑与新逻辑分离,把旧逻辑抽出去:

var horribleCode = function(){
  console.log(我是一堆你看不懂的老逻辑')

}

var _horribleCode = horribleCode

horribleCode = function() {

    _horribleCode()
    console.log('我是新的逻辑')

}

horribleCode()

学会了装饰器的套路再用 ES6 巩固一下吧

// 把原来的老逻辑代码放在一个类里
class HorribleCode () {
    control() {
         console.log(我是一堆你看不懂的老逻辑')
    }
}

// 老代码对应的装饰器
class Decorator {

    // 将老代码实例传入
     constructor(olHC) {
        this.oldHC = oldHC
    }

    control() {

        this.oldHC.control()
        // “包装”了一层新逻辑
        this.newHC()
    }

    newHC() {

        console.log('我是新的逻辑')
    }
}


const horribleCode = new HorribleCode()
//这里我们把老代码实例传给了 Decorator,以便于后续 Decorator 可以进行逻辑的拓展。
const decorator = new Decorator(horribleCode)

decorator.control()

ES7 为我们提供了语法糖可以给一个类装上装饰器,继续改造上面的代码

// 装饰器函数,它的第一个参数是目标类
function Decorator(target) {
    target.control = function() {
        console.log('我是新的逻辑')
    }
    return target
}


// 将装饰器“安装” 到HorribleCode上
@Decorator
class HorribleCode () {
    //老代码逻辑
}


HorribleCode.control()

去装饰类里面的方法:

function Decorator(target, name, descriptor) {
    let originalMethod = descriptor.value
    descriptor.value = function() {
        console.log('我是Func的装饰器逻辑')
        console.log('我是新的逻辑')
        return originalMethod.apply(this, arguments)
     }
     return descriptor
}

class HorribleCode {
    @Decorator
    control() { 
         console.log('我是一堆你看不懂的老逻辑')
    }
}

// 验证装饰器是否生效
const horribleCode = new HorribleCode()
horribleCode.control()

总结

自问自答

1、继承与装饰器相比有什么缺点

(1)继承的方式并不灵活,会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之改变;

(2)在继承方式中,超类的内部细节是对子类可见的,继承常常被认为破坏了封装性。

(3)在完成一些功能复用的同时,有可能创建出大量的子类, 使子类的数量呈爆炸性增长。(在我们玩英雄联盟时,每个英雄都有很多皮肤,如果改成用类实现,10个英雄,10款皮肤,100个类啊!)

编辑于 2019-12-11 17:38