2012-12-06 140 views
1

我試圖讓一個裝飾圖案上班follwingJavaScript的裝飾模式

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

我可能會錯過一些點,但如我所料的模式是行不通的。

如果我添加兩個裝飾器,並將它們添加到一個類中,功能不會像我想象的那樣通過。只能調用最後一個裝飾器的函數,或者調用基本的裝飾器。鏈接被打破。我該如何解決?

我添加了一個小提琴:

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

UPDATE:更正的版本

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);? 
+0

在設備原型函數中,它應該是'this.brightness',而不是'this.device.brightness'對於其他設備是一樣的。 –

+0

修復了它,謝謝 – pfried

+0

只要一件事:你可以使用Object.create(deviceDecorator.prototype)而不是新的deviceDecodrator。這隻會做鏈接,並避免實際運行構造函數。 (舊的瀏覽器可能沒有這個功能,在這種情況下,它是一個非常簡單的墊片,它可能也應該在許多庫中可用) – hugomg

回答

3

你的第一個裝飾返回device.getID(函數本身),而不是調用它並返回它返回的值。

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

此外,還要確保你的資本是一致的。

+0

謝謝你的回答。我還有一個小問題:我爲設備的一個屬性設置了一個setter,比如亮度。我能以某種方式訪問​​原始設備嗎?因爲如果沒有傳遞,以後定義功能是不可能的,如果我想在原始設備上執行 – pfried

+0

我想出另一種方式來完成裝飾器模式。我認爲這好多了:http://jsfiddle.net/Hh2vt/3/ – pfried