装饰器模式
装饰器模式是指在不改变原有对象的基础上, 对其进行包装扩展, 使其满足用户更复杂的需求.
复习下单例模式
使用单例模式维护一个全局的 Modal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <style> div { width: 200px; height: 200px; border: 1px solid pink; color: pink; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); } </style> <title>Document</title> </head> <body> <button id="open">open</button> <button id="hidden">hidden</button> <script> const Modal = (function() { let modal = null return function() { if (!modal) { modal = document.createElement('div') modal.style.display = 'none' modal.innerText = 'Modal' document.body.appendChild(modal) } return modal } })()
document.getElementById('open').addEventListener( 'click', function() { const modal = new Modal() console.log(modal)
modal.style.display = 'block' }, false )
document.getElementById('hidden').addEventListener( 'click', function() { const modal = new Modal() modal.style.display = 'none' }, false ) </script> </body> </html>
|
问题来了
这时候产品经理说, 需要修改下这个按钮文字内容, 还要给点击按钮置灰, 不可点击, 如果我们在项目多处用到的话, 就需要一处处进行修改
如果封装成公共组件, 也会因为组件应用时的需求复杂度而产生同样的问题
装饰器模式改造案例
第一步 抽离原有旧逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const Modal = (function() { let modal = null return function() { if (!modal) { modal = document.createElement('div') modal.style.display = 'none' modal.innerText = 'Modal' document.body.appendChild(modal) } return modal } })()
function openModal() { const modal = new Modal() if (modal) { modal.style.display = 'block' } }
|
第二步 封装新需求逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function changeBtnText() { const btn = document.getElementById('open') btn.innerText = '快点我' }
function disabledBtn() { const btn = document.getElementById('open') btn.setAttribute('disabled', true) }
function changeBtnStatus() { changeBtnText() disabledBtn() }
|
第三步 添加需求到点击按钮上
1 2 3 4 5 6 7 8
| document.getElementById('open').addEventListener( 'click', function() { openModal() changeBtnStatus() }, false )
|
ES6 class 类实现装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| class Modal { constructor() { this.modal = null } static getModal() { if (!this.modal) { this.modal = document.createElement('div') this.modal.innerText = '我是一个class单例模式下的div' this.modal.style.display = 'none' document.body.appendChild(this.modal) } return this.modal } }
class openModal { click() { const modal = Modal.getModal() modal.style.display = 'block' } }
class Decorator { constructor(open_button) { this.open_btn = open_button }
onclick() { this.open_btn.click() this.changeBtnStatus() }
changeBtnStatus() { this.changeBtnText() this.disabledBtn() }
changeBtnText() { const btn = document.getElementById('open') btn.innerText = '来点击我啊' }
disabledBtn() { const btn = document.getElementById('open') btn.setAttor = '来点击我啊' } }
document.getElementById('open').addEventListener( 'click', function() { const openBtn = new openModal() const btn = new Decorator(openBtn) btn.onclick() }, false )
|