(七)装饰器模式
裝飾器模式
- 裝飾器模式
- 裝飾器模式 介紹
- 概念
- 示例
- 裝飾器模式 演示
- 裝飾器模式 場景
- ES7 裝飾器
- 裝飾類
- 裝飾方法
- core-decorators
- 裝飾器模式 總結(jié)
裝飾器模式
- 介紹
- 演示
- 場景
- 總結(jié)
裝飾器模式 介紹
- 為對(duì)象添加新功能
- 不改變其原有的結(jié)構(gòu)和功能
概念
裝飾器模式(Decorator Pattern)允許向一個(gè)現(xiàn)有的對(duì)象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它是作為現(xiàn)有的類的一個(gè)包裝。動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來說,裝飾器模式相比生成子類更為靈活。
示例
手機(jī)上套一個(gè)殼可以保護(hù)手機(jī),殼上粘一個(gè)指環(huán),可以掛在手指上不容易滑落,這就是一種裝飾。手機(jī)還是那個(gè)手機(jī),手機(jī)的功能一點(diǎn)都沒變,只是在手機(jī)的外面裝飾了一些其他附加的功能。日常生活中,這樣的例子非常多。
裝飾器模式 演示
通常的 UML 類圖
去掉父子類的繼承(前端少用),簡化之后的類圖是
代碼演示
class Circle {draw() {console.log('畫一個(gè)原型')} }class Decorator {constructor(circle) {this.circle = circle}draw() {this.circle.draw()this.setRedBoder(circle)}setRedBoder(circle) {console.log('設(shè)置紅色邊框')} }// 測試代碼 let circle = new Circle() circle.draw()let dec = new Decorator(circle) // 裝飾 dec.draw()結(jié)合本示例,聯(lián)想一下開始介紹的手機(jī)殼,是一個(gè)道理,都是外面加一層裝飾,且不改變原有功能。
裝飾器模式 場景
就 ES7 標(biāo)準(zhǔn)中增加的裝飾器來體會(huì)一下裝飾器模式在 JS 中的應(yīng)用。
如果node -v是6.x版本的話,要安裝npm i babel-plugin-transform-decorators-legacy --save-dev,然后修改.babrlrc
{"presets": ["es2015", "latest"],"plugins": ["transform-decorators-legacy"] }另外注意,裝飾器是在編譯時(shí)執(zhí)行的而不是運(yùn)行時(shí)。
ES7 裝飾器
參考 http://es6.ruanyifeng.com/#docs/decorator
裝飾類
先看一個(gè)最簡單的 demo ,體會(huì)一下裝飾器
// 一個(gè)簡單的 demo @testDec class Demo {// ... }function testDec(target) {target.isDec = true; } alert(Demo.isDec) // true可以加參數(shù)
// 可以加參數(shù) function testDec(isDec) {return function(target) {target.isDec = isDec;} }@testDec(true) class Demo {// ... } alert(Demo.isDec) // true裝飾器的原理
// 裝飾器的原理@decorator class A {}// 等同于class A {} A = decorator(A) || A;最后一個(gè)示例
function mixins(...list) {return function (target) {Object.assign(target.prototype, ...list)} }const Foo = {foo() { alert('foo') } }@mixins(Foo) class MyClass {}let obj = new MyClass(); obj.foo() // 'foo'裝飾方法
先看一個(gè) readonly 的 demo
function readonly(target, name, descriptor){// descriptor 屬性描述對(duì)象(Object.defineProperty 中會(huì)用到),原來的值如下// {// value: specifiedFunction,// enumerable: false,// configurable: true,// writable: true// };descriptor.writable = false;return descriptor; }class Person {constructor() {this.first = 'A'this.last = 'B'}// 裝飾方法@readonlyname() { return `${this.first} ${this.last}` } }var p = new Person() console.log(p.name()) // p.name = function () {} // 這里會(huì)報(bào)錯(cuò),因?yàn)?name 是只讀屬性再看一個(gè)例子,加一個(gè)裝飾器自動(dòng)打印日志
function log(target, name, descriptor) {var oldValue = descriptor.value;descriptor.value = function() {console.log(`Calling ${name} with`, arguments);return oldValue.apply(this, arguments);};return descriptor; }class Math {// 裝飾方法@logadd(a, b) {return a + b;} }const math = new Math(); const result = math.add(2, 4); // 執(zhí)行 add 時(shí),會(huì)自動(dòng)打印日志,因?yàn)橛?@log 裝飾器 console.log('result', result);core-decorators
- 第三方開源lib
- 提供常用的裝飾器
- 查閱文檔:core-decorators
core-decorators.js 是一個(gè)第三方模塊,提供了幾個(gè)常見的修飾器,通過它可以更好地理解修飾器。
用之前肯定得先安裝npm i core-decorators --save,然后先用它來實(shí)現(xiàn)上述的 readonly
// 首先安裝 npm i core-decorators --save// 開始編碼: import { readonly } from 'core-decorators'class Person {@readonlyname() {return 'zhang'} }let p = new Person() alert(p.name()) // p.name = function () { /*...*/ } // 此處會(huì)報(bào)錯(cuò)在看一個(gè)常用的例子,對(duì)已經(jīng)棄用的協(xié)議,給出警告。
import { deprecate } from 'core-decorators';class Person {@deprecatefacepalm() {}@deprecate('We stopped facepalming')facepalmHard() {}@deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' })facepalmHarder() {} }let person = new Person();person.facepalm(); // DEPRECATION Person#facepalm: This function will be removed in future versions.person.facepalmHard(); // DEPRECATION Person#facepalmHard: We stopped facepalmingperson.facepalmHarder(); // DEPRECATION Person#facepalmHarder: We stopped facepalming // // See http://knowyourmeme.com/memes/facepalm for more details.具體的使用,可再去參考官網(wǎng)。
裝飾器模式 總結(jié)
- 什么是裝飾器模式
- 使用場景
- 核心:不改變原來的,增加裝飾
- ES7 裝飾器
設(shè)計(jì)原則驗(yàn)證:
- 將現(xiàn)有對(duì)象和裝飾器進(jìn)行分離,兩者獨(dú)立存在
- 符合開放封閉原則
總結(jié)
- 上一篇: 唯品会如何找取件码(汉典唯字的基本解释)
- 下一篇: (八)代理模式