[英]How to implement the Decorator Design pattern in javascript?
誰能幫助我在javascript中實現Decorator設計模式。 我有一個TankBase實體:
TankBase = function (x, y, width, height, direction, imageOptions) {
TankBase.base.call(this, x, y, width, height, imageOptions);
this.speed = 250;
this.direction = direction;
this.render = function (drawEngine) {
drawEngine.render();
};
...
}
我想使用裝飾器模式添加新功能。 例如,我想修改render()函數並在罐下繪制一個健康指示器:
var TankHealthDecorator = function (tank) {
var _tank = tank;
this.render = function (drawEngine) {
// draw a health indicator
...
_tank.render(drawEngine);
};
}
用法:
var tank = new TankHealthDecorator(new HeavyTank());
HeavyTank在其中繼承TankBase。
我應該如何修改TankHealthDecorator()使其像坦克實例的包裝一樣使用?
編輯:
保羅,謝謝你的精彩文章:
我將從這里開始:addyosmani.com/blog/decorator-pattern寫得很好。 –保羅
從功能上講,我認為您所擁有的非常接近。 我將存儲原始的渲染功能,分配一個新的渲染功能,然后僅在裝飾后的功能中應用它。 我也沒有看到需要將裝飾器創建為對象,但這可能更像是一種偏好。
var DrawEngine = { render: function() {
console.log('render');
} };
var TankBase = function (x, y, width, height, direction, imageOptions) {
this.speed = 250;
this.direction = direction;
this.render = function (drawEngine) {
drawEngine.render();
};
};
var HeavyTank = function() {
TankBase.apply(this, arguments);
this.render = function() {
console.log('heavyTank Render');
}
}
function DecorateTankWithHealthIndicator (tank) {
var oRender = tank.render;
tank.render = function (drawEngine) {
console.log('draw a health indicator');
oRender.apply(tank, arguments);
};
};
var btank = new TankBase();
var htank = new HeavyTank();
btank.render(DrawEngine);
htank.render(DrawEngine);
DecorateTankWithHealthIndicator(btank);
DecorateTankWithHealthIndicator(htank);
btank.render(DrawEngine);
htank.render(DrawEngine);
在以下方法中,將tankBase對象傳遞給tankHealth函數。 在tankHealth函數中修改tankBase對象,將tankBase對象保存在var that
。 改造后that
被返回修改后的tankBase對象。
var TankBase = function () {
this.render = function () {
console.log('tankBase')
};
}
var TankHealthDecorator = function (tank) {
var that = tank;
that.render = function() {
console.log('tankHealth')
};
return that;
}
window.onload = function(){
var tankBase = new TankBase();
var testHealth = new TankHealthDecorator(new TankBase());
tankBase.render(); // tank base
testHealth.render(); // tank health
};
這是Decorator模式的粗略實現-AKA: 包裝器 :
修飾模式通常用於添加額外的責任到對象動態地將請求轉發到其接受組件, 和|或解耦深繼承層次結構是集成在類型 (不與組合模式混淆-這是集成在層次 -使用Component-Leaf結構,允許在統一的,分形的拓撲結構中進行同義請求(平等對待父級和子級))。
function AbstractComponent(){
this.draw = function(){
console.log('@AbstractComponent | #draw');
};
}
function AbstractDecorator(){
AbstractComponent.call(this); // Inherit AbstractComponent Interface
this.notify = function(){
console.log('@AbstractDecorator | #notify');
};
}
function ConcreteComponent(options){
AbstractComponent.call(this); // Inherit AbstractComponent Interface
this.fill = function(){
console.log('@ConcreteComponent | #fill');
};
}
function ConcreteDecorator(Component){
AbstractDecorator.call(this); // Inherit AbstractDecorator Interface
function PrivateResponsibility(){
console.log('@ConcreteDecorator | #PrivateResponsibility');
}
this.additionalResponsibility = function(){
console.log('@ConcreteDecorator | #additionalResponsibility');
};
this.draw = function(){
console.log('@ConcreteDecorator | #draw-Component.draw');
// ... additional logic
PrivateResponsibility();
Component.draw();
};
this.fill = function(){
console.log('@ConcreteDecorator | #fill-Component.fill');
Component.fill();
};
}
var concreteComponent = new ConcreteComponent();
concreteComponent = new ConcreteDecorator(concreteComponent); // use same variable name as to allow client code to remain the same
//CLIENT CODE
concreteComponent.draw();
concreteComponent.fill();
concreteComponent.notify();
concreteComponent.additionalResponsibility();
以下是我對功能(對象)裝飾的理解
function api_decorator(some_data){
return function decorator(func){
return function new_function(args){
/* do somethinfg with data before and after func */
console.log("I'm code before with data: "+some_data);
func(args);
console.log("I'm code after");
}
}
}
function somefunc(data){
console.log("Hi, I'm func "+data);
}
somefunc("without decoration")
/* injecting somefunc in decorator api */
somefunc=api_decorator("data needed for api")(somefunc)
/* calling decorated with api somefunc */
somefunc("with decoration")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.