Used to treat single objects or collections of objects in the same way
Compositions are used to create nested structures of nodes
- a node may be a single node (leaf) or a container of nodes
- the ability to iterate through the composite beginning from any node and moving up the tree
What we will be doing:
Step 1 – Page: node.js
// JavaScript Document
define(function () {
'use strict';
var Person = function (name) { //set up Person object constructor
this.name = name; //add name to a property of the object
this.children = []; //add children as property and set to empty aray
this.parent = null; //add parent as property as set to null
};
Person.prototype.addChild = function (child) { //set up method to add children to Person object
this.children.push(child); //push the child arguement into the children array for the object
child.parent = this; //create a reciprocal link by setting current person as parent of child passed to the method. We need this reciprocal link so we can traverse up and down the tree
};
Person.prototype.traverseUp = function () { //set up method to traverse up
if (this.parent) { //check whether current object has parent
console.log(this.name + ' is the child of ' + this.parent.name); //if it does, log out a message
this.parent.traverseUp(); //then invoke traverseUp method of parent
} else { // if there are no parents
console.log(this.name + ' is the root node'); //we then know this is a root node
}
};
Person.prototype.traverseDown = function () { //set up traverseDown
if (this.children.length) { //check for children
this.children.forEach(function (child) { //if so, iterate through children collection
console.log(this.name + ' is the parent of ' + child.name); //send out log statement
child.traverseDown(); //then invoke traverseDown on child
}, this);//set the context for the forEach method, so inside the handler, this still refers to current person objects
} else { //if no children
console.log(this.name + ' is a leaf node'); //then object is a leaf node
}
};
return Person; //return the person constructor
});
Step 2 – Page: init.js
define(function(require) {
'use strict';
return {
init: function() {
var Node = require('composite/node'), //require in node.js
root = new Node('Fred'), //set up nodes, al nodes are created in same way
child1 = new Node('John'),
child2 = new Node('Jane'),
child3 = new Node('Jack'),
child4 = new Node('Jill'),
child5 = new Node('James'),
child6 = new Node('Jess')
root.addChild(child1); //add two children to root node, then leave child1 as leaf
root.addChild(child2);
child2.addChild(child3); //add child nodes to child2, making it a container
child2.addChild(child4);
child4.addChild(child5); //leave child3 as leaf, and make child4 a container with one child
child5.addChild(child6); //child5 is container, and child6 is lowest leaf on the tree
root.traverseDown(); //displays entire tree
root.traverseUp(); //root is the top level, so returns that root is a root node
child6.traverseUp(); //displays entire tree
child6.traverseDown(); //bottom level, so returns that Jess is a leaf node with no children
}
};
});
Step 3 – Page: main.js
// JavaScript Document
require (
['composite/init'],
function (composite) {
'use strict';
var examples = {
composite: composite
};
window.runExample = function (example) {
examples[example].init();
};
}
);
Conclusion
Main purpose of composite pattern is to allow single objects or collections of objects to be used in the same way
- we don’t need to know if object is container or leaf, we can process it the same way.