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