你不知道的javascript设计模式(十五)----装饰者模式

前言

        同学们,上一章节我们介绍了中介者模式,中介者模式应用于对象关系复杂的场景,将所有对象之间的交互集中到中介对象处,来降低对象之间的耦合性,这一章节,我们将进一步学习一种新的设计模式,装饰者模式

正文

装饰者模式的定义

        装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类派生的其他类。比如说,你去买炸串,你想吃辣一点的,老板就给你的炸串多放了点辣椒粉,但是给你的那部分炸串放辣椒粉并不会影响到其他的炸串,也并不会因为老板给你炸串放多了点辣椒粉,你吃的就不是炸串了,它还是炸串,只不过是辣点的炸串。
        在这个场景中,辣椒粉就是装饰者,而给炸串放辣椒粉让它比别的炸串更辣但是不影响它炸串本身性质的过程就是装饰者模式

装饰者模式的实现

        和之前一样,在实现装饰者模式之前,我们先引入一个业务场景来方便大家理解,我们大家应该玩过飞机大战的小游戏,随着等级的提升,我们的飞机也会发出不一样的子弹,假设平时,我们发射的就是小子弹,等我们第一次升级的时候,就可以发射导弹,第二次升级的时候,就可以解锁激光炮,这里我们尝试用装饰者模式对这个场景实现一下,首先我们先实现一下最基本的飞机类型

var Plane = function() {}
Plane.prototype.shoot = function() {
	console.log('发射子弹');
}

        然后我们需要再实现两个装饰类型去让飞机类型可以发射处导弹和激光炮

var guidedMissle = function(plane) {
	this.plane = plane;
}
guidedMissle.prototype.shoot = function () {
	this.plane.shoot();
	console.log('发射导弹');
}
var laserGun = function(plane) {
	this.plane = plane;
}
laserGun.prototype.shoot = function () {
	this.plane.shoot();
	console.log('发射激光炮');
}

        我们可以发现使用导弹和激光炮的装饰类型,并不会影响到飞机类本身的操作,飞机类本身还是会发射子弹,装饰类只是额外给了被装饰者对象本身不具备的能力而不会影响到它已经有的能力,就像开篇说的炸火腿肠多加点辣椒粉,并不会因为多加了辣椒粉,炸火腿肠的味道就不是火腿肠的味道了,只是额外赋予了一种辣的味道

基于javascript的装饰者模式实现

        在刚学习设计模式的时候,我们就介绍到javascript是一种基于原型的语言,上一小结我们按照类型来定义,对于javascript而言其实是不必要的,我们可以直接通过修改对象或者给对象增加方法来实现,并不需要借助“类”来实现装饰者模式

var plane = {
	shoot: function() {
		console.log('发射子弹');
	}
}
var guidedMissle = function() {
	console.log('发射导弹');
}
var laserGun = function() {
	console.log('发射激光炮');
}
var shoot = plane.shoot;
plane.shoot = fucntion() {
	shoot();
	guidedMissle();
	laserGun();
}

        在javascript中,函数作为一类对象,我们可以很轻松地给函数对象本身扩展一些功能,像上面这样实现,但是不可避免地会污染到原函数本身,这样其实是不符合开放-封闭原则的

用AOP装饰函数

        在职责链的部分我们在Function的原型上实现了after方法,实际上我们只要实现before和after方法,然后把装饰者的方法传进去就可以实现装饰者模式

Function.prototype.before = function(beforefn) {
	var _self = this;
	return function() {
		beforefn.apply(this, arguments);
		return _self.apply(this, arguments);
	}
}
Function.prototype.after = function(afterfn) {
	var _self = this;
	return function() {
		var ret = _self.apply(this, arguments);
		afterfn.apply(this, arguments);
		return ret;
	}
}

        利用我们之前定义的方法就可以比较轻松地实现装饰者模式了

var shoot = plane.shoot.before(guidedMissle).after(laserGun);
shoot(); 
// 发射子弹
// 发射导弹
// 发射子弹
// 发射激光炮

        但是这样其实还有一个小问题,会污染Function的原型方法,所以考虑到这一点,我们可以把before和after提取出来单独做一个方法,下面以before为例:

var before = function(fn, beforefn) {
	return function() {
		beforefn.apply(this, arguments);
		return fn.apply(this, arguments);
	}
}

小结

        这一章我们学习了装饰者模式,装饰者模式在js中是很好实现的一种设计模式,但是如果直接在函数中进行扩展,会对原函数造成污染,不符合开放-封闭原则,所以我们介绍了怎么利用AOP去实现装饰者模式,因为AOP本身就是以装饰者模式为远离的编程思想,所以可以比较好地实现它
       小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!
       每天学习进步一点点,就是领先的开始。如果想继续提高,欢迎关注我,或者关注公众号”祯民讲前端“。大量前端技术文章,面试资料,技巧等助你更进一步!
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值