设计模式(4): 装饰器模式

模式导入
以一个简单的例子让我们来了解一下装饰器模式:已有一个类完成相应的功能,同时,需要为这个类或者方法添加一些额外的功能或者属性,我们可以将这个已有的类或者方法进行包装,包装的过程中不能够影响类或者方法原有的内容,所做的只是额外的装饰处理。
以一个生活中的例子来看,装饰器模式就好比是给手机套手机壳,只是为了给手机起一个保护作用,但并不会影响手机的正常使用
官方概念
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
场景需求

  1. 当我们需要为一个原有的类添加一些新的属性和方法时,可以使用装饰器模式进行类的包装,避免直接修改原有类的内容
  2. 为一些类或者方法添加附加的内容,比如给一个方法的运行打印日志,或者是限制一个方法为只读的(readonly)等等

    代码实现

es6中使用Js实现一个装饰器模式
es7中如何使用装饰器完成类或者方法的装饰

  • 使用Es6的方式实现一个打印日志的操作
// 定义一个普通的类实现简单的加法操作
class Math{
	add(a, b){
		return a + b;
	}
}

// 定义装饰器类
class Decorator{
	constructor(math){
		this.math = math;
	}
	add(a, b){
		console.log("...class Math with add function execute...")
		return this.math.add(a, b)
	}
}

// 测试装饰器:
const math = new Math()
const decMath = new Decorator(math)
decMath.add(1, 2)

代码注解: 我们定义一个Math的类,同时定义一个Decorator的装饰类,它接收需要装饰的math的对象作为参数,对这个对象进行一些简单的附加操作。
可能大家会觉得这样的方式很low,所以我们来看看es7中如何使用装饰器来优雅的实现装饰操作

  • es7中实现装饰器
// 定义一个简单的实现两数相加的操作:
class Math{
	@decLog("...class Math with add function execute...")
	add(a, b){
		return a + b;
	}
}
// 定义打印日志的装饰器方法:
function decLog(log){
	return function(target, name, descriptor){
		const value = descriptor.value;
		descriptor.value = function(){
			console.log(log)
			return value.apply(this, arguments)
		}
		return descriptor;
	}
}

// 测试
const math = new Math()
console.log(math.add(1, 2))

代码注解: es7中我们可以使用类似其他语言中的装饰器的方法,使用@符号进行类和方法的装饰,其中装饰器都是一个函数,在类的装饰器函数中,我们可以接收到的是这个类的构造函数,在方法的装饰器中还可以接收到的是这个方法的名字和一个操作器可以对方法进行只接的修改。其实这些和在Ts中的实现是相似的,大家可以看我的另一篇博客中介绍Ts的中的装饰器的内容。
然后需要注意的是,Es7的语法在很多的浏览器中没法兼容,大家可以使用parcel打包编译代码,同时安装一个babel的插件: babel-plugin-transform-decorators-legacy 同时添加到.babelrc文件中即可使用es7中装饰器的内容了。
附上.babelrc中的内容:

{
    "plugins": [
        "transform-decorators-legacy"
    ]
}

关于装饰器,附上我Ts装饰器的博客地址,和es7中装饰器的语法类似,可以参考:https://blog.csdn.net/qq_44746132/article/details/105227181


好了关于装饰器模式我们就说到这里了, 大家 加油!!!

你可能感兴趣的:(设计模式,设计模式)