这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战
介绍
本期我们来聊聊装饰器模式,它可以动态地给一个对象添加一些额外的职责,又不会影响到原来的功能,这可比生成子类更为灵活,是一种常见的设计模式,它也是继承的一种替代方案。
举个栗子吧,魂斗罗相信我们小时候都玩过,主角移动过程中会吃到各式各样的BUFF,吃完后武器就会发生变化,有的是霰弹枪,有的是喷火,有的是激光等等各式各样的效果,但是射击动作执行并没有改变,改变的只是武器的射击效果,这时就可以用装饰器模式来去追加/更改这些武器效果。
概念
装饰器模式属于一种结构型模式,它是作为现有的类的一个包装。主要是允许向一个现有的对象添加新的功能,同时又不改变其结构。
案例
接下来,就是要实现一下魂斗罗的武器切换。
var player = {
fire:function(){
console.log("—执行射击—")
}
}
var weaponS = function(){
console.log("*霰弹武器*")
}
var weaponF = function(){
console.log("*喷火武器*")
}
var weaponL = function(){
console.log("*激光武器*")
}
var _player_fire = player.fire;
player.fire = function(){
_player_fire();
weaponS();
}
player.fire()
console.log("~~~~~~切换武器~~~~~~~")
player.fire = function(){
_player_fire();
weaponF();
}
player.fire()
console.log("~~~~~~切换武器~~~~~~~")
player.fire = function(){
_player_fire();
weaponL();
}
player.fire()
这里我们就看到了,我们并没有更改player原本的动作没有修改,而是仅仅的将武器的功能进行了扩展,而且切换也不会产生对原有的射击动作产生影响。
ES装饰器
因为涉及到装饰器模式的业务确实非常多,在 ES7 中提出了一个装饰器的新语法。
装饰器是一种函数,写成@ + 函数名。
它可以放在类和类方法的定义前面,可以十分方便的用来装饰整个类。
@decorator
class className {}
// 等同于
class className {}
className = decorator(className) || className;
但目前依然是一个提案状态,以后是否有更改依然未知。
使用场景
- 扩展一个类的功能。
- 动态增加功能,动态撤销。
结语
通过刚才的讲述不难发现,装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能,十分的灵活。
我们在开发中,比如日志统计,头像框装饰替换等等,都可以考虑使用它来完成。