views:

96

answers:

4

I'm implementing a decorator pattern in Javascript.

I've seen the example here in Wikipedia

// Class to be decorated
function Coffee() {
    this.cost = function() {
 return 1;
    };
}

// Decorator A
function Milk(coffee) {
    this.cost = function() {
 return coffee.cost() + 0.5;
    }; 
}

// Decorator B
function Whip(coffee) {
    this.cost = function() {
 return coffee.cost() + 0.7;
    };
}

// Decorator C
function Sprinkles(coffee) {
    this.cost = function() {
 return coffee.cost() + 0.2;
    };
}

// Here's one way of using it
var coffee = new Milk(new Whip(new Sprinkles(new Coffee())));
alert( coffee.cost() );

// Here's another
var coffee = new Coffee();
coffee = new Sprinkles(coffee);
coffee = new Whip(coffee);
coffee = new Milk(coffee);
alert(coffee.cost());

Now my question is for the pattern to still be a decorator pattern, does it matter if the parent class is called at the beginning or the end of the cost() function?

Now granted I realize that this depends on what each of the decorators do...for instance if your are multiplying or dividing in your decorator instead of adding or subtracting, it will of course warrant a different result.

But is there any reason to make the call before or after other than the reason I stated in the previous paragraph?

+1  A: 

It does not matter. The decorator is supposed to change the way an object behaves, how it does it is purely a matter of implementation.

ASk
hmm okay I can accept that...that is if anyone else agrees and votes ASk up before I do...
leeand00
+1  A: 

You are clearly interested in programming, and quite skilled, but be aware that talking about a true anything is dangerous. Programming has very few simple answers, and if you think you have found one, somebody is taking advantage of you.

Instead simply learn as many tools as you can, learn the advantages and disadvantages of them and know when they are appropriate and when they require modification.

tomjen
I just wondered if the order in which they were called had anything to do with if the pattern was a decorator pattern or not. *shrugs*
leeand00
Like if it would cause someone else to not be able to recognize the pattern as a decorator.
leeand00
A: 

Be careful of

new X(new Y(new Z())))

type constructions. This has several pitfalls (I'm a Java guy so I mention a couple of Java examples, but the concepts really apply anywhere)

  • You don't have access to the nested objects

    • Sometimes you need it, like if you're decorating Java IO objects and a close() fails, you need to try closing the nested objects)
    • Sometimes you need or want to set extra data
    • Sometimes you need to get a result out of the nested item (new PrintWriter(new StringWriter()) -- you need to get the resulting String from the StringWriter
  • If you get an exception (or other type of error) it's hard to tell what happened based on the reported line number

  • It's harder to step through when debugging (depends on the debugger)
  • It's harder to insert something in the middle
  • It's harder to remove something in the middle
  • It's harder to re-arrange the order
Scott Stanchfield
I'm a former Java guy myself, and Javascript tends to be a bit more flexible than I remeber Java being (with the exception of Groovy of course)But what I do need is dynamic extension at runtime. And this is the only way I know of setting that up...
leeand00
Actually, if you do have a hard time debugging this sort of thing you should think about using AOP (SpringAOP) along with a good logging framework like log4j.Sure it isn't debugging but in cases like this logging is even better.
leeand00
(than debugging)
leeand00
I'm not saying you're doing it wrong; I'm just saying you may want to prefer the separate-line approach you listed.
Scott Stanchfield
A: 

Okay found the answer.

I went back and re-read the Decorator Pattern part of my design patterns book and found:

"The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job."

With the emphasis being on the before and/or after bit...

Sorry to have bothered you and thanks for the answers.

leeand00