【问题标题】:JavaScript Decorator PatternJavaScript 装饰器模式
【发布时间】:2012-12-06 13:51:51
【问题描述】:

我正在尝试让装饰器模式如下工作

http://www.joezimjs.com/javascript/javascript-design-patterns-decorator/

我可能错过了一些要点,但该模式没有按我的预期工作。

如果我添加两个装饰器并将它们添加到一个类中,则函数不会像我想的那样传递。只能调用最后一个装饰器的函数或调用基本的装饰器。链子坏了。我该如何解决这个问题?

我加了一个小提琴:

http://jsfiddle.net/hbyLW/25/

更新:更正版本

http://jsfiddle.net/hbyLW/29/

以及源代码:

// A basic device class
var device = function(options) {
    this.brightness = options.brightness;
    this.Id = options.Id;
    this.motion = options.motion;
};

// Adding some functions to the class
device.prototype = {

    getID: function() {
        console.log("This ID:" + this.device.Id);
        return this.Id;
    },
    getBrightness: function() {
        console.log("This Brightness: " + this.brightness);
        return this.brightness;
    },
    getMotion: function() {
        console.log("This Motion: " + this.motion);
        return this.motion;
    }
};

// A device Decorator 
var deviceDecorator = function(device) {
    this.device = device;
};

// Adding pass through functions to the Decorator
deviceDecorator.prototype = {
    getId: function() {
        console.log("Old Id");
        return this.device.getId;
    },
    getBrightness: function() {
        console.log("Old Brightness");
        return this.device.getBrightness;
    },
    getMotion: function() {
        console.log("Old Motion");
        return this.device.getMotion;
    }
};

// A Decorator that adds some functionality to the getBrightness function
var brightnessDecorator = function(device) {
    deviceDecorator.call(this, device);
};

brightnessDecorator.prototype = new deviceDecorator();

brightnessDecorator.prototype.getBrightness = function() {
    this.device.getBrightness();
    console.log("Changed Brightness");
};

var motionDecorator = function(device) {
    deviceDecorator.call(this, device);
};

// A Decorator that adds some functionality to the getMotion function
motionDecorator.prototype = new deviceDecorator();

motionDecorator.prototype.getMotion = function() {
    this.device.getMotion();
    console.log("changed Motion");
};

// Some options for a device
var options = {
    Id: "Identifier",
    brightness: true,
    motion: false
};

// Create a new device
var Lamp = new device(options);
// Add the decorators to the device
Lamp = new brightnessDecorator(Lamp);
Lamp = new motionDecorator(Lamp);

// Executing the functions
Lamp.getId();
Lamp.getMotion();
Lamp.getBrightness();
console.log(Lamp);?

【问题讨论】:

  • 在设备原型函数中,它应该是this.brightness 而不是this.device.brightness 其他的也是如此。
  • 只有一件事:你可以使用 Object.create(deviceDecorator.prototype) 而不是 new deviceDecodrator。这仅进行链接并避免实际运行构造函数。 (虽然旧的浏览器可能没有这个功能。在这种情况下,它是一个非常容易制作的填充程序,它可能也应该在许多图书馆中都可用)

标签: javascript design-patterns decorator


【解决方案1】:

您的第一个装饰器返回device.getID(函数本身),而不是调用它并返回它返回的值。

deviceDecorator.prototype = {
  getID: function() {
    console.log("Old Id");
    return this.device.getID(); // <= call function instead of returning it
  },
  ...
}

另外,请确保您的大小写一致。

【讨论】:

  • 感谢您的回答。我还有第二个小问题:我有一个设备属性之一的设置器,比如亮度。我可以以某种方式访问​​原始设备吗?因为如果已经没有直通,如果我想在原始设备上操作,以后定义功能是不可能的
  • 我想出了另一种方法来做装饰器模式。我认为这要好得多:jsfiddle.net/Hh2vt/3
猜你喜欢
  • 2018-09-19
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 2018-04-10
  • 2012-02-04
  • 1970-01-01
相关资源
最近更新 更多