装饰器模式

1.装饰器模式,它的定义是“在不改变元对象的基础上,通过对其包装拓展,是原有对象可以满足用的更复杂需求。”
比如水墨屏的手机壳,就是一个标准的装饰器,它不会对手机原有的功能产生任何影响,仅仅使手机多了块屏幕。
2.为什么会有装饰器模式?
因为任何人在去做需求的时候,都不想关心它现有的业务逻辑是什么样的,只想对它已有的功能做拓展,只关心拓展功能如何实现。于是便有了装饰器模式。
3.装饰器怎么实现?
首先,将旧逻辑与新逻辑分离,把旧逻辑封装起来。
然后编写新逻辑。
最后把新逻辑旧逻辑整合到一起。
ES5的实现

document.getElementById('open').addEventListener('click', function() {
    openModal() // 旧逻辑
    changeButtonStatus() //新逻辑
})

ES6的实现

// 定义打开按钮
class OpenButton {
    // 点击后展示弹框(旧逻辑)
    onClick() {
        const modal = new Modal()
        modal.style.display = 'block'
    }
}

// 定义按钮对应的装饰器
class Decorator {
    // 将按钮实例传入
    constructor(open_button) {
        this.open_button = open_button
    }
    
    onClick() {
        this.open_button.onClick()
        // “包装”了一层新逻辑
        this.changeButtonStatus()
    }
    
    changeButtonStatus() {
        this.changeButtonText()
        this.disableButton()
    }
    
    disableButton() {
        const btn =  document.getElementById('open')
        btn.setAttribute("disabled", true)
    }
    
    changeButtonText() {
        const btn = document.getElementById('open')
        btn.innerText = '快去登录'
    }
}
const openButton = new OpenButton()
const decorator = new Decorator(openButton)

document.getElementById('open').addEventListener('click', function() {
    // openButton.onClick()
    // 此处可以分别尝试两个实例的onClick方法,验证装饰器是否生效
    decorator.onClick()
})

4.ES7的装饰器函数
可装饰类,也可装饰类里面的方法

// 将装饰器“安装”到Button类上
@classDecorator
class Button {
    // Button类的相关逻辑
}
//装饰类的方法
class Button {
    @funcDecorator
    onClick() { 
        console.log('我是Func的原有逻辑')
    }
}

5.装饰器语法糖帮我们做了些什么
(1)函数传参&调用
给类添加装饰器时,target是被装饰的类本身

function classDecorator(target) {
    target.hasDecorator = true
    return target
}

给方法添加装饰器时,target变成了类的原型对象。

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

装饰器函数调用的时机:装饰器函数在编译阶段就执行了。
(2)传入“属性描述对象”descriptor
对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
它由各种各样的属性描述符组成,这些描述符又分为数据描述符和存取描述符:

  • 数据描述符:包括 value(存放属性值,默认为默认为 undefined)、writable(表示属性值是否可改变,默认为true)、enumerable(表示属性是否可枚举,默认为 true)、configurable(属性是否可配置,默认为true)。
  • 存取描述符:包括 get 方法(访问属性时调用的方法,默认为 undefined),set(设置属性时调用的方法,默认为 undefined )
    拿到了 descriptor,就相当于拿到了目标方法的控制权。通过修改 descriptor,我们就可以对目标方法的逻辑进行拓展了~

参考:
JavaScript设计模式之装饰器模式1
JavaScript设计模式之装饰器模式2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容

  • github所有关于设计模式的代码:js学习设计模式记录 1.适配器模式 使用场景:旧接口与使用者不兼容,中间添加...
    疯狂吸猫阅读 428评论 0 0
  • 什么是装饰器模式 ES6/ES7中的装饰器模式简而言之就是对现有类进行一个包装,不通过子类或者改变其内部结构的方式...
    _章鱼小丸子阅读 386评论 0 0
  • 介绍 为对象添加新功能 不改变其原有的结构和功能和适配器模式不一样,适配器模式是原有的不能用了,而装饰器模式是原来...
    林海_Mense阅读 3,475评论 0 3
  • 装饰器模式 装饰器模式是一种旨在提升代码复用率的结构性模式。有点类似于混入模式,它被认为是一种可以替代子类的可行方...
    pws019阅读 344评论 0 0
  • 8.门面模式 8.1.课程目标 1、掌握门面模式和装饰器模式的特征和应用场景 2、理解装饰器模式和代理模式的根本区...
    我是阿喵酱阅读 910评论 0 1