js设计模式——装饰器模式

113 阅读1分钟

什么是装饰器?装饰器模式干了什么事情?

装饰器在我看来就是一个函数,该函数实现了对类、方法的扩展,提高了代码的复用性。

背景

某一天,我接到一个需求:写一个全局唯一的弹框(单例模式),点击后弹出文字'登录后查看'。话不多说开始编码:

// css html 忽略
// js如下
class Modal{
    createInstance(){
        // 如果没有实例,则创建一个实例赋值给 Modal.instance
        if(!Modal.instance){
            Modal.instance = document.createElement('div')
            Modal.instance.id= "modal" // 元素id
            Modal.instance.innerText = "登录后查看" // 元素内容
            document.body.append(Modal)
        }
        // 如果存在实例,则直接返回
        return Modal.instance
    }
}
document.getElementById('open').addEventListener('click',()=>{
  const modal = Modal.createInstance()
  model.style.display = "block"
})
document.getElementById('close').addEventListener('click',()=>{
    const modal = Modal.createInstance()
    if(modal){
        model.style.display = "none"
    }
})

又来活了

代码平稳运行几天后,不料下个迭代又有一个关于这个需求:点击后需要把按钮的内容改为"去登录",且禁用该按钮

思考一下,如果使用装饰器模式,怎么实现?

ES5实现方式

// 把修改按钮和修改按钮的href的方法提成一个新方法
function openModal(){
  const modal = Modal.createInstance()
  model.style.display = "block"
}
function changeBtnStatus(){
  const btn = document.getElementById('open')
  btn.innerText = "去登录"
  btn.setAttribute('disabled','true')
}
document.getElementById('open').addEventListener('click',()=>{
  openModal()
  changeBtnStatus()
})

ES6实现方式,面向对象

class Modal{
    openModal(){
      const modal = Modal.createInstance()
      model.style.display = "block"
    }
}
class BtnDecorator extends OpenBtn{
    changeBtnStatus(){
      const btn = document.getElementById('open')
      btn.innerText = "去登录"
      btn.setAttribute('disabled','true')
    }
    openModal(){
      super.openModal()
      this.changeBtnStatus()
    }
}
document.getElementById('open').addEventListener('click',()=>{
  const btnDecorator = new BtnDecorator()
  btnDecorator.openModal() // 实现了修饰器的思想
})

推荐一个库

core-decorators,实现了许多的装饰器以供使用。