javascript设计模式:装饰者模式

Posted Nyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript设计模式:装饰者模式相关的知识,希望对你有一定的参考价值。

装饰者模式 (Decorator Pattern)又称装饰器模式,在不改变原对象的基础上,通过对其添加属性或方法来进行包装拓展,使得原有对象可以动态具有更多功能。

本质是功能动态组合,即动态地给一个对象添加额外的职责,就增加功能角度来看,使用装饰者模式比用继承更为灵活。好处是有效地把对象的核心职责和装饰功能区分开,并且通过动态增删装饰去除目标对象中重复的装饰逻辑。

一、装饰者模式生活实例

房屋装修,当毛坯房建好的时候,已经可以居住了,虽然不太舒适。一般我们自己住当然不会住毛坯,因此我们还会通水电、墙壁刷漆、铺地板、家具安装、电器安装等等步骤,让房屋渐渐具有各种各样的特性,比如墙壁刷漆和铺地板之后房屋变得更加美观,有了家具居住变得更加舒适,但这些额外的装修并没有影响房屋是用来居住的这个基本功能,这就是装饰的作用。

喝的奶茶,除了奶茶之外,还可以添加珍珠、波霸、椰果、仙草、香芋等等辅料,辅料的添加对奶茶的饮用并无影响,奶茶喝起来还是奶茶的味道,只不过辅料的添加让这杯奶茶的口感变得更多样化。

比如去咖啡厅喝咖啡,点了杯摩卡之后我们还可以选择添加糖、冰块、牛奶等等调味品,给咖啡添加特别的口感和风味,但这些调味品的添加并没有影响咖啡的基本性质,不会因为添加了调味品,咖啡就变成奶茶。

在类似场景中,这些例子有以下特点:

  1. 装饰不影响原有的功能,原有功能可以照常使用;
  2. 装饰可以增加多个,共同给目标对象添加额外功能;

二、代码实现

function OriginHouse() { }

OriginHouse.prototype.getDesc = function () {
    console.log("空房子");
}

function Furniture(house) {
    this.house = house;
}
Furniture.prototype.getDesc = function () {
    this.house.getDesc();
    console.log("搬入家具");
}

function Painting(house) {
    this.house = house;
}

Painting.prototype.getDesc = function () {
    this.house.getDesc();
    console.log("刷房子")
}
let house = new OriginHouse()
house = new Furniture(house)
house = new Painting(house)

// house.getDesc()

var originHouse = {
    getDesc() {
        console.log("origin house");
    }
}

function furniture() {
    console.log("furniture");
}

function painting() {
    console.log("painting");
}
originHouse.getDesc = function () {
    var getDesc = originHouse.getDesc;
    return function () {
        getDesc();
        furniture();
        painting();
    }
}()
originHouse.getDesc();

 

 

 

 在表现形式上,装饰者模式和适配器模式比较类似,都属于包装模式。在装饰者模式中,一个对象被另一个对象包装起来,形成一条包装链,并增加了原先对象的功能。

三、实战中的装饰者模式

  • 给浏览器事件添加新功能

之前介绍的添加装饰器函数的方式,经常被用来给原有浏览器或 DOM 绑定事件上绑定新的功能,比如在 onload 上增加新的事件,或在原来的事件绑定函数上增加新的功能,或者在原本的操作上增加用户行为埋点:

window.onload = function() {
    console.log(\'原先的 onload 事件 \')
}

/* 发送埋点信息 */
function sendUserOperation() {
    console.log(\'埋点:用户当前行为路径为 ...\')
}

/* 将新的功能添加到 onload 事件上 */
window.onload = function() {
    var originOnload = window.onload
    return function() {
        originOnload && originOnload()
        sendUserOperation()
    }
}()

// 输出: 原先的 onload 事件
// 输出: 埋点:用户当前行为路径为 ...

可以看到通过添加装饰函数,为 onload 事件回调增加新的方法,且并不影响原本的功能,我们可以把上面的方法提取出来作为一个工具方法:

function originDecorationFn(originObj, originKey, fn) {
    originObj[originKey] = function() {
        var originFn = originObj[originKey];
        return function() {
            originFn && originFn();
            fn();
        }
    }()
}
window.onload = function() {
    console.log(\'原先的 onload 事件 \')
}

function sendUserOperation() {
    console.log(\'埋点:用户当前行为路径为 ...\');
}
originDecorationFn(window, \'onload\', sendUser, sendUserOperation);

 

以上是关于javascript设计模式:装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

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

JavaScript设计模式中的装饰者模式

JavaScript设计模式中的装饰者模式

JavaScript设计模式与开发实践 装饰者模式

javascript设计模式——装饰者模式

Javascript设计模式之装饰者模式详解篇