<h1>Composite Pattern</h1>
<p>In the composite pattern, a type is able to contain members of it's super type. This Fiddle shows a simple example of the pattern where the Super type is represented by a File and the Sub type by a Folder. In a conventional file structure a Folder is a type of file but can contain files and other folders</p>
<p>The composite pattern is useful for building tree like structures where each node should provide a common interface</p>
<p>There are two main types involved in the composite pattern: A Base type which provides an interface and common functionality; and a Composite type which can contain a number of other types, both Base and Composite.</p>
<p>In a tree like structure, instances of the Base type function as leaf nodes whilst instances of the Composite type function as ancestor nodes.</p>
<p>Composite types must maintain a reference to each of it's contained children, whilst each type which exists in a Composite type must maintain a reference to it's parent. It is advised that this relationship is set up within the composite type</p>
<p>Run the example and view the output in the console. The code uses some Javascript functionality which is only currently available in Firefox</p>
</p>
JavaScript
// composite pattern example. (Firefox only)
var filesize1 = 24;
var filesize2 = 56;
var filesize3 = 13;
function extend(Parent, Child) {
function F() {}
F.prototype = Parent.prototype;
Child.prototype = new F();
}
function File(name, filesize) {
this.name = name;
this.size = filesize;
}
File.prototype = {
getName: function () {
return this.name;
},
getFileSize: function () {
return this.size;
},
// demonstrates calling up parent chain for context information
getPath: function (pathComponent) {
pathComponent = pathComponent || "";
pathComponent = "/" + this.getName() + pathComponent;
if (this.parent) {
return this.parent.getPath(pathComponent);
} else {
return pathComponent;
}
}
}
function Folder(name) {
File.call(this, name, 0);
this.files = [];
}
extend(File, Folder);
// demonstrates delegating to constituent parts
Folder.prototype.getFileSize = function () {
return this.files.reduce(function (initial, file) {
return initial + file.getFileSize();
}, 0);
};
Folder.prototype.addFile = function (file) {
this.files.push(file);
// create reference to parent
file.parent = this;
}
Folder.prototype.addFiles = function (...files) {
files.forEach(function (file) {
this.addFile(file);
}, this);
}
var client = {
run: function () {
var rootfolder = new Folder("root-folder");
var folder = new Folder("my-folder");
rootfolder.addFile(folder);
var file1 = new File("file1", filesize1);
var file2 = new File("file2", filesize2);
var file3 = new File("file3", filesize3);
folder.addFiles(file1, file2, file3);
console.log("my new folder is called: ", folder.getName());
console.log("folderSize is: ", folder.getFileSize());
console.log("folderPath is: ", file1.getPath());
...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.