深入理解JavaScript系列(29):设计模式之装饰者模式详解

作者:半夏

时间:2026-10-28

浏览:642

本文详解JavaScript中的装饰者模式,阐述其作为继承替代方案的弹性优势。通过Macbook配置、任务执行及圣诞树装饰三个实例,演示如何在不修改原有类的前提下,动态地为对象添加新功能。文章对比了装饰者与继承的区别,并提供了完整的代码实现与执行流程分析,帮助开发者理解如何区分核心职责与装饰功能。

文章目录

装饰者模式概述

介绍

装饰者模式提供了一种比传统继承更具灵活性的替代方案。它通过包装具有相同接口的对象,允许在运行时向方法添加行为,同时保留对原始对象方法的调用能力(例如通过装饰者的构造函数访问)。

该模式通过重载方法的形式来添加新功能,可以在被装饰对象的行为执行前后插入自定义逻辑,从而实现特定的业务目的。

装饰者模式的核心优势

正文

装饰者模式的主要优势在于其动态性。与继承不同,在子类中增加行为会影响该类的所有实例,而装饰者允许为不同的对象实例单独添加新行为,互不干扰。如下代码所示:

代码如下:

//需要装饰的类(函数)
function Macbook() {
this.cost = function () {
return 1000;
    };
}
function Memory(macbook) {
 this.cost = function () {
 return macbook.cost() + 75;
 };
}
function BlurayDrive(macbook) {
 this.cost = function () {
 return macbook.cost() + 300;
 };
}
function Insurance(macbook) {
 this.cost = function () {
 return macbook.cost() + 250;
 };
}
// 用法
var myMacbook = new Insurance(new BlurayDrive(new Memory(new Macbook())));
console.log(myMacbook.cost());

装饰者模式的应用实例

另一个实例展示了当在装饰者对象上调用performTask时,它不仅执行装饰者自身的逻辑,还会调用底层对象的performTask函数。

代码如下:

function ConcreteClass() {
this.performTask = function () {
this.preTask();
console.log('doing something');
this.postTask();
    };
}
function AbstractDecorator(decorated) {
 this.performTask = function () {
 decorated.performTask();
 };
}
function ConcreteDecoratorClass(decorated) {
 this.base = AbstractDecorator;
 this.base(decorated);
decorated.preTask = function () {
 console.log('pre-calling..');
 };
decorated.postTask = function () {
 console.log('post-calling..');
 };
}
var concrete = new ConcreteClass();
var decorator1 = new ConcreteDecoratorClass(concrete);
var decorator2 = new ConcreteDecoratorClass(decorator1);
decorator2.performTask();

综合示例:圣诞树装饰

再来看一个更彻底的示例:

代码如下:

var tree = {};
tree.decorate = function () {
console.log('Make sure the tree won\'t fall');
};
tree.getDecorator = function (deco) {
 tree[deco].prototype = this;
 return new tree[deco];
};
tree.RedBalls = function () {
 this.decorate = function () {
 this.RedBalls.prototype.decorate(); // 第7步:先执行原型(这时候是Angel了)的decorate方法
 console.log('Put on some red balls'); // 第8步 再输出 red
 // 将这2步作为RedBalls的decorate方法
 }
};
tree.BlueBalls = function () {
 this.decorate = function () {
 this.BlueBalls.prototype.decorate(); // 第1步:先执行原型的decorate方法,也就是tree.decorate()
 console.log('Add blue balls'); // 第2步 再输出blue
 // 将这2步作为BlueBalls的decorate方法
 }
};
tree.Angel = function () {
 this.decorate = function () {
 this.Angel.prototype.decorate(); // 第4步:先执行原型(这时候是BlueBalls了)的decorate方法
 console.log('An angel on the top'); // 第5步 再输出angel
 // 将这2步作为Angel的decorate方法
 }
};
tree = tree.getDecorator('BlueBalls'); // 第3步:将BlueBalls对象赋给tree,这时候父原型里的getDecorator依然可用
tree = tree.getDecorator('Angel'); // 第6步:将Angel对象赋给tree,这时候父原型的父原型里的getDecorator依然可用
tree = tree.getDecorator('RedBalls'); // 第9步:将RedBalls对象赋给tree
tree.decorate(); // 第10步:执行RedBalls对象的decorate方法

总结

总结

装饰者模式是一种在运行时动态为已有功能添加更多功能的方式。它将每个装饰功能封装在单独的函数中,并用该函数包装被装饰的已有函数对象。当需要执行特殊行为时,调用代码可以根据需要选择性地、按顺序地使用装饰功能来包装对象。其优点是将类(或函数)的核心职责与装饰功能分离开来。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章