Javascript 装饰器模式 - 原型(prototype)还是单一函数?

标签 javascript design-patterns decorator

我正在阅读 Addy Osmani 的关于装饰器模式的教程(可在 http://addyosmani.com/blog/decorator-pattern/ 找到),并且我对如何在 Javascript 中实现最简单的装饰器有点困惑。似乎有些示例使用 obj.prototype 模式向现有对象添加功能,有些示例创建独立函数并传递对象。

// Decorator Pattern ?
function coffee(size, flavors) {
    this._size = size || "medium";
    this._flavors = flavors || [];   
    this._cost = 100;
    this.info = function() {
        console.log(this._size, this._flavors, this._cost);
    }
}

// Decorator - Would this be considered a decorator since the functionality needed to add flavors default to the coffee object?

function addFlavor(coffee, flavor) {
    coffee._flavors.push(flavor);
    coffee._cost = coffee._cost + 25;
}

// Decorator - Engrave the cup? lol
function engraving(coffee) {
    coffee._cost = coffee._cost + 200;
}

// Decorator Variation w/ prototype instead - Add cream
coffee.prototype.addCream = function () { 
    this._cost = this._cost + 100;
};

// Instantiate Coffee
testCoffee = new coffee('Large', ['vanilla']);

// Add Flavors
addFlavor(testCoffee, 'chocolate');
addFlavor(testCoffee, 'almond');
addFlavor(testCoffee, 'hazelnut');

// Add Engraving
engraving(testCoffee);

// Add Cream
testCoffee.addCream();

// Log it all to the console
testCoffee.info();

可以在此处找到此示例的 JsFiddle:http://jsfiddle.net/pathsofdesign/ocbbzoy2/

<小时/>

我的问题:看起来我可以使用原型(prototype)继承来实现装饰器模式。这样做有什么优点或缺点(即:我的 addCream() 方法)? 谢谢!

更新:

看起来我的示例实际上根本没有实现装饰器模式。 @Etai 和 @Bergi 在下面都给出了很好的答案。如果我理解正确的话,传统的 JS Decorator 会“包装”另一个 obj,然后在不修改基础对象的情况下调整该特定对象的行为。

最佳答案

没有。你所拥有的不是装饰器,它们只是方法。方法确实会改变对象,装饰器通过覆盖方法来改变行为。它们与 mixins 非常相似,只是它们不创建新方法。

例如,让我们为您的 Coffee 类提供一个 setSize 方法:

Coffee.prototype.setSize = function(size) {
    this._size = size || 'medium';
};

现在,让我们来看看一个疯狂的咖啡师,他的比例不正确:

function extreme(coffee) {
    var oldMethod = coffee.setSize;
    coffee.setSize = function(size) {
        oldMethod.call(this, size && 'Xtra'+size[0].toUpperCase()+size.slice(1));
    };
}

让他端上一份“大”的菜:

> var coffee = extreme(new Coffee);
> coffee.setSize("large")
> coffee.info()
XtraLarge, Array [], 100

关于Javascript 装饰器模式 - 原型(prototype)还是单一函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26107091/

相关文章:

javascript - React 类属性与 ES6 类属性

oop - 接口(interface)隔离原则——程序到接口(interface)

java - 在 CDI 装饰器之间共享数据

python-3.x - 如何在 Python 中使用类装饰器混合行为?

javascript - 如何将函数作为属性传递给 React 组件?

javascript - 如何对 html5 输入进行模式化

javascript - 使用 moment.js 检测当前用户时区的 ID

c++ - 我可以创建单例子类吗?

c# - 构建器设计模式在现实生活中的用途是什么?

python - 我可以获得应用于函数的装饰器列表吗?