设计模式 ~ 装饰器模式

一、概念

  • 允许在不改变原有对象的基础上,通过将对象包装在一个装饰器对象中来动态地添加额外的功能或责任;
  • 简单地说: 允许向一个现有的对象添加新的功能,同时又不改变其结构
  • 装饰器和目标是分离和解耦的

二、演示

  • 以下示例中,定义了一个装饰器函数 decorator,接受一个函数作为参数,并返回一个新的函数;
  • 该新函数就是 HOC 高阶函数,在调用原始函数之前可以做一些其他事情,常用于实现日志记录、性能追踪、缓存等功能的封装,以及在框架和库中为现有类添加新的功能
function decorator(originalFunc) {
  return function () {
  	// ... do something
    return originalFunc.apply(this, arguments)
  }
}
function sayHello(name) {
  console.log('Hello,', name) // Hello, zhangsan
}
var decoratedSayHello = decorator(sayHello)
decoratedSayHello('zhangsan')
  • Decorator 相当于一个装饰,有自己的属性和方法,同时可以也执行目标上的方法;
class Circle {
    draw() {
        console.log('画一个圆')
    }
}
class Decorator {
    constructor(circle) {
        this.circle = circle
    }
    draw() {
        this.circle.draw()
        console.log('画一个边')
    }
}
const decorator = new Decorator(new Circle())
decorator.draw()

  • TS : tsconfig 需要设置支持装饰器模式 "experimentalDecorators": true
  • @为装饰器特定标识
// 装饰器工厂函数
function decorato(val: boolean) {
    // 装饰器
    return function (target: any) {
        target.isTestable = val
    }
}

@decorato(false) // 等同于 decorato(false)(DecoratorFoo)
class DecoratorFoo {
    static isTestable?: boolean
}
console.log(DecoratorFoo.isTestable) // false
  • Foo 中的方法 getName 的属性描述符 writable 通过装饰器函数 readOnly 修改为 fasle
function readOnly(val: boolean) {
    return function (target: any, key: string, descriptor: PropertyDescriptor) {
        descriptor.writable = val
    }
}

class Foo {
    @readOnly(false) // 等同于 readOnly(false)(Foo)
    sayHi() {}
}
const f = new Foo()
// @ts-ignore
console.log(Object.getOwnPropertyDescriptor(f.__proto__, 'sayHi'))
import { connect } from 'react-redux'
export default TodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList)
@connect(mapStateToProps, mapDispatchToProps)
export default TodoList extends React.Component { }

AOP

  • 面向切面编程,使得页面和系统基础功能分离,如 redux-thunk
/**
 * 记录日志
 * @param target 实例
 * @param key 属性键值对
 * @param descriptor 属性描述符
 */
function log(target: any, key: string, descriptor: PropertyDescriptor) {
    console.log(target)
    console.log(key)
    console.log(descriptor)
    const oldValue = descriptor.value // fn1
    // 重新定义 business
    descriptor.value = function () {
        console.log(`记录日志 ...`)
        return oldValue.apply(this, arguments)
    }
}

class Foo {
    @log
    business() {
        console.log('业务')
    }
}

const f = new Foo()
f.business()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值