How methods called/linked sequentially in decorator design pattern?

how methods called/linked sequentially in decorator design pattern?
when call last line 4 alerts called - well how move from alert 1 to 2 to 3? tested success but explanation not understood…

// Decorator Pattern

var tree = {};
tree.decorate = function () {
  alert('Make sure the tree won\'t fall');
};

tree.getDecorator = function (deco) {
  tree[deco].prototype = this;
  return new tree[deco];
};

tree.RedBalls = function () {
  this.decorate = function () {
    this.RedBalls.prototype.decorate();
    alert('Put on some red balls');
  };
};

tree.BlueBalls = function () {
  this.decorate = function () {
    this.BlueBalls.prototype.decorate();
    alert('Add blue balls');
  };
};

tree.Angel = function () {
  this.decorate = function () {
    this.Angel.prototype.decorate();
    alert('An angel on the top');
  };
};

tree = tree.getDecorator('BlueBalls');
tree = tree.getDecorator('Angel');
tree = tree.getDecorator('RedBalls');
console.log(tree);
tree.decorate();
1 Like

Hi,

To explain why the output occurs as it does, let’s have a look at what the code is doing:

Initially, tree is an empty object.
We then add a bunch of methods to it:

console.log(tree);
> Object {
    decorate: function, 
    getDecorator: function, 
    RedBalls: function, 
    BlueBalls: function, 
    Angel: function
  }

We then change the value of tree, by assigning it the return value of tree’s getDecorator method, when invoked with the parameter 'BlueBalls'

tree = tree.getDecorator('BlueBalls');
console.log(tree);
> tree.BlueBalls {
    decorate: function, 
    getDecorator: function, 
    RedBalls: function, 
    BlueBalls: function, 
    Angel: function
  }

So what has gone on there?

Inside tree’s getDecorator method, we have:

tree.getDecorator = function (deco) {
  tree[deco].prototype = this;
  return new tree[deco];
};

this refers to our tree object.
tree[deco] resolves to tree.BlueBalls, which is a property of the tree object.
The value of tree.BlueBalls is an anonymous function.
The prototype property of tree.BlueBalls is initially the Function prototype object.

The method then sets the prototype property of tree.BlueBalls to tree.
And returns a new instance of tree.BlueBalls

It’s worth noting that when the new operator is invoked, it first creates a new object:

tree.BlueBalls {}

The [[prototype]] property of tree.BlueBalls (the new object) is then set to the current object value of the tree.BlueBalls.prototype

tree.BlueBalls {
  __proto__: Object
    Angel: function () {
    BlueBalls: function () {
    RedBalls: function () {
    decorate: function () {
    getDecorator: function (deco) {

The tree.BlueBalls function is also executed, which overides the decorate() method in the tree super-class:

tree.BlueBalls {
  decorate: function () {
    __proto__: Object
      Angel: function () {
      BlueBalls: function () {
      RedBalls: function () {
      decorate: function () {
      getDecorator: function (deco) {

We can demonstrate this, thus:

console.log(tree.decorate)
> function () {
    this.BlueBalls.prototype.decorate();
    console.log('Add blue balls');
}  

console.log(tree.__proto__.decorate);
> function () {
    this.BlueBalls.prototype.decorate();
    console.log('Make sure the tree won\'t fall');
}  

Now we can kick this off:

tree = tree.getDecorator('BlueBalls');
tree.decorate();
> Make sure the tree won't fall
  Add blue balls

What has happened is that we have invoked tree’s decorate method.
This in turn invokes it’s prototype’s decorate method.
The prototype’s decorate method outputs Make sure the tree won't fall to the console.
Execution returns to tree’s decorate method, it logs Add blue balls to the console.


Now, what happens when we add tree = tree.getDecorator('Angel')?

The variable tree (which at this point is an instance of tree.BlueBalls), doesn’t have a getDecorator method, so JavaScript checks its [[prototype]] to find one.

tree.getDecorator = function (deco) {
  tree[deco].prototype = this;
  return new tree[deco];
};

When this getDecorator method is invoked for a second time, it returns an instance of tree.Angel.
This is similar to tree.BlueBalls, except that its prototype is tree.BlueBalls, not our original tree object.

console.log(tree);
tree.Angel {
  decorate: function () {
    __proto__: tree.BlueBalls
      decorate: function () {
      __proto__: Object
        Angel: function () {
        BlueBalls: function () {
        RedBalls: function () {
        decorate: function () {
        getDecorator: function (deco) {

Now if we run everything again, we get:

tree = tree.getDecorator('BlueBalls');
tree = tree.getDecorator('Angel');
tree.decorate();
> Make sure the tree won't fall
  Add blue balls
  An angel on the top 

This is because when tree.decorate() is called, tree is an instance of tree.Angel.
tree.decorate first invokes it’s prototype’s (tree.BlueBalls) decorate method.
tree.BlueBalls invokes it’s prototype’s decorate method, which logs Make sure the tree won't fall
Execution then returns to tree.BlueBalls’s decorate method, which logs Add blue balls
Execution finally returns to tree.Angel’s decorate method, which logs An angel on the top

The same thing happens again when we reassign the value of tree in the following line:

tree = tree.getDecorator('RedBalls');

I hope that helps.

I find the terminology for all of this a little tricky, so I would be grateful if anyone fancied improving my explanation.

4 Likes

I thought you did a stellar job on the terminology, all the way down to prototype vs [[prototype]]. :smile:

There might be ways to improve the code examples to make it seem more straightforward.

  1. The method decorate perhaps shouldn’t be named that. “Decorate”, a verb, makes it sound like this is the method that performs the decorating. Maybe it’s just because it’s Friday, but every time I saw this.decorate, I had to remind myself that, despite its name, it doesn’t actually do any decorating. In fact it’s the method being decorated, and it could be any arbitrary method.

  2. The object being decorated perhaps shouldn’t also be responsible for creating the decorators. I feel like that muddies the waters a bit. The object being decorated needn’t be aware that any decorators exist at all.

I’ll be back on later and I can take a shot at an alternative code example. I’m a little disappointed that the current code example came from what I would otherwise consider to be a good JavaScript book.

First a pseudo-classical example.

// First, a simple object type.
// This can be used all by itself, and it doesn't need to know or care whether any decorators exist.

    function Tree() {
    }

    Tree.prototype.getLeafColor = function () {
        return 'Green';
    };

    Tree.prototype.getBarkColor = function () {
        return 'Brown';
    };


// Next, a base decorator object type from which all Tree decorators will inherit.
// It accepts as a parameter an existing tree object,
// and it re-implements Tree's interface by forwarding all calls to that tree parameter.

    function AbstractTreeDecorator(tree) {
        this.tree = tree;
    }

    AbstractTreeDecorator.prototype.getLeafColor = function () {
        return this.tree.getLeafColor();
    };

    AbstractTreeDecorator.prototype.getBarkColor = function () {
        return this.tree.getBarkColor();
    };


// Now we're going to make some concrete Tree decorators.
// Each concrete decorator inherits from the base decorator,
// which means they each accept as a parameter an existing tree object,
// and they each forward all calls to that tree parameter.

    function FallTreeDecorator() {
        // In JavaScript, constructors don't inherit automatically.
        // We need to manually invoke the super constructor.
        AbstractTreeDecorator.apply(this, arguments);
    }

    // This is where JavaScript's inheritance magic happens
    FallTreeDecorator.prototype = Object.create(AbstractTreeDecorator.prototype);
    FallTreeDecorator.constructor = FallTreeDecorator;

    // We're going to override one of the methods.
    FallTreeDecorator.prototype.getLeafColor = function () {
        return 'Yellow';
    };


// Another concrete Tree decorator.

    function SnowyTreeDecorator() {
        AbstractTreeDecorator.apply(this, arguments);
    }

    SnowyTreeDecorator.prototype = Object.create(AbstractTreeDecorator.prototype);
    SnowyTreeDecorator.constructor = SnowyTreeDecorator;

    SnowyTreeDecorator.prototype.getLeafColor = function () {
        return this.tree.getLeafColor() + ', covered in snow';
    };

    SnowyTreeDecorator.prototype.getBarkColor = function () {
        return this.tree.getBarkColor() + ', covered in snow';
    };


// Here's how we could use these.

    // A regular tree
    var tree = new Tree();
    tree.getLeafColor(); // Green
    tree.getBarkColor(); // Brown

    // A fall tree
    var fallTree = new FallTreeDecorator(tree);
    fallTree.getLeafColor(); // Yellow
    fallTree.getBarkColor(); // Brown

    // A snowy tree
    var snowyTree = new SnowyTreeDecorator(tree);
    snowyTree.getLeafColor(); // Green, covered in snow
    snowyTree.getBarkColor(); // Brown, covered in snow

    // A snowy fall tree
    var snowyFallTree = new SnowyTreeDecorator(fallTree);
    snowyFallTree.getLeafColor(); // Yellow, covered in snow
    snowyFallTree.getBarkColor(); // Brown, covered in snow

1 Like

Next an example that uses more prototypal inheritance.

One of the most onerous parts of the decorator pattern is in the base abstract decorator, where we have to re-implement the interface of the object being decorated. In this case, Tree had only two methods, so it wasn’t too bad, but what if there were 10? Or 50? It can become a pain. Fortunately, JavaScript’s prototype chain can supply that behavior for us, where a call to one object is automatically forwarded to another.

// First, a simple object type.
// This can be used all by itself, and it doesn't need to know or care whether any decorators exist.

    function Tree() {
    }

    Tree.prototype.getLeafColor = function () {
        return 'Green';
    };

    Tree.prototype.getBarkColor = function () {
        return 'Brown';
    };


// In this alternate implementation, there's no need for a base abstract decorator.
// It's purpose has been replaced with JavaScript's prototype chain.
// So we can go straight to making some concrete Tree decorators.

    function addFallTreeDecorator(tree) {
        // Create a new, blank object whose [[Prototype]] is the tree object being decorated
        var decoratedTree = Object.create(tree);

        // We're going to override one of tree's methods
        decoratedTree.getLeafColor = function () {
            return 'Yellow';
        };

        return decoratedTree;
    }


// Another tree decorator.

    function addSnowyTreeDecorator(tree) {
        var decoratedTree = Object.create(tree);

        decoratedTree.getLeafColor = function () {
            return tree.getLeafColor() + ', covered in snow';
        };

        decoratedTree.getBarkColor = function () {
            return tree.getBarkColor() + ', covered in snow';
        };

        return decoratedTree;
    }


// Here's how we could use these.

    // A regular tree
    var tree = new Tree();
    tree.getLeafColor(); // Green
    tree.getBarkColor(); // Brown

    // A fall tree
    var fallTree = addFallTreeDecorator(tree);
    fallTree.getLeafColor(); // Yellow
    fallTree.getBarkColor(); // Brown

    // A snowy tree
    var snowyTree = addSnowyTreeDecorator(tree);
    snowyTree.getLeafColor(); // Green, covered in snow
    snowyTree.getBarkColor(); // Brown, covered in snow

    // A snowy fall tree
    var snowyFallTree = addSnowyTreeDecorator(fallTree);
    snowyFallTree.getLeafColor(); // Yellow, covered in snow
    snowyFallTree.getBarkColor(); // Brown, covered in snow
1 Like

Thanks. I appreciate that.

Right. This made it somewhat more difficult to follow.

As did this. My experience of the decorator pattern thus far, was to create a base object and progressively add additional decorators to provide the extra capabilities.


So, regarding your code examples, I have a couple of questions (I'm hoping the OP won't mind). I slimmed down the code to remove the SnowyTreeDecorator. Here's a [fiddle][1] so you can see what I'm working with.

My questions:

  1. Do you create the base decorator object solely so that any other decorators have the same interface as the component they are decorating?

  2. Does this:

    AbstractTreeDecorator.apply(this, arguments);

    cause our FallTreeDecorator to inherit AbstractTreeDecorator’s methods and properties?

  3. Could you expand a little more on this:

    // This is where JavaScript's inheritance magic happens
    FallTreeDecorator.prototype = Object.create(AbstractTreeDecorator.prototype);
    FallTreeDecorator.constructor = FallTreeDecorator;
    

Implementing this in Ruby, I would probably use a module:
class Tree
  def get_leaf_colour
    "Green"
  end

  def get_bark_colour
    "Brown"
  end
end

module FallTree
  def get_leaf_colour
    "Yellow"
  end
end

tree = Tree.new
puts tree.get_leaf_colour #green
puts tree.get_bark_colour #brown

fall_tree = tree.extend(FallTree)
puts fall_tree.get_leaf_colour #yellow
puts fall_tree.get_bark_colour #brown

That’s half of it. But yes, a decorator must provide the same interface as the decoratee so that the two can be used interchangeably. That way, for example, some part of the program that’s expecting to work on a Tree object could actually be passed a tree decorator object and it wouldn’t know the difference, because all the same method calls would work.

In addition, the decorator needs to forward method calls to the decoratee. In the pseudo-classical style, we need to write this out manually, which can be a tedious task, so it’s useful to write it once then inherit that behavior so you don’t have to repeatedly write it out in every concrete decorator.

So when the concrete decorators inherit from the base decorator, they get both the same interface as the decoratee and they get the method forwarding behavior.

I don’t know Ruby well enough to say much about this, but assuming that tree.extend returns a new object with the methods of FallTree mixed in and inherits in some way from tree, then absolutely, that seems perfectly right.

You may have noticed that when a language’s inheritance model is objects inheriting directly from other objects, as JavaScript and seemingly Ruby do, (as opposed to classes inheriting from other classes) then the decorator pattern becomes almost stupidly simple.

Now I understand my decor DP JavaScript script… although I’m little confused with other replies.

Thanks!