您现在的位置是:首页 >学无止境 >设计模式之装饰器模式网站首页学无止境

设计模式之装饰器模式

前端吕小布 2023-07-19 00:00:03
简介设计模式之装饰器模式

装饰器模式:为对象添加新功能,不改变其原有的结构和功能
装饰器模式是原有的功能还能用,但是需要新增一些东西来完善这个功能。比如产品经理让你添加新功能,但又要保证原来的代码不变,你要在原来的方法执行的时候同时出现新功能。比如手机壳,手机本身的功能不受影响,手机壳就是手机的装饰器模式。
比如有个方法,它的功能是:

let handle = () => {
	alert(1)
};

新需求是,你要在执行handle函数的时候,顺便再弹出一个2。

这里正常改的话,可能就写成这样:

//修改代码
let handle = () => {
	alert(1)
	alert(2)
};

但,我们说这样写其实就违反了开闭原则,而且,如果这里的alert(1)并不是一句简单的执行语句,而是一堆复杂的逻辑代码,而alert(2)也并不是简单的alert(2),这个时候,怎么办呢?
我们可以这么写:

//扩展函数
const _handle = handle;
handle = () => {
	_handle();
	alert(2);
}

我们可以新建一个变量_handle先将原函数保存一下原函数的引用,然后扩展一下handle,执行刚保存的原函数_handle,然后将自己的功能扩展在原函数的下面。

回顾装饰器模式的定义:“在不改变原对象的基础上,对原对象进行包装扩展”,我们发现这里就是一个装饰器模式的应用。

类实现装饰器

class Circle {
  draw() {
    console.log('画一个圆形');
  }
}
class Decorator {
  constructor(circle) {
    this.circle = circle;
  }
  draw() {
    this.circle.draw();
    this.setRedBorder(circle);
  }
  setRedBorder(circle) {
    console.log('设置红色边框')
  }
}
// 测试
let circle = new Circle();

let client = new Decorator(circle);
client.draw();  // 17.画一个圆形 29.设置红色边框

使用场景

ES7装饰器
1、安装 npm i babel-plugin-transform-decorators-legacy
在.babelrc文件配置代码:

{
    "presets": ["es2015", "latest"],
    "plugins": ["transform-decorators-legacy"]
}

2、代码

// 一个简单的demo
@testDec
class Demo {
    // ...
}
function testDec(target) {
    target.isDec = true
}
alert(Demo.isDec) // true

打印出来了true,说明@testDec这个装饰器已经成功了,函数是个装饰器,用@testDec给Demo装饰了一遍。这个target其实就是class Demo,然后给她加一个isDec

原理

// 装饰器原理
@decorator
class A {}

// 等同于
class A {}
A = decorator(A) || A;

传参的形式

@testDec(false)

class Demo {
}

function testDec(isDec) {
    return function (target) {
        target.isDec = isDec
    }
}

alert(Demo.isDec);

设计原则验证

将现有对戏那个和装饰器进行分离,两者独立存在
符合开放封闭原则

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。