Skip to content

Instantly share code, notes, and snippets.

@OriginUnknown
Created July 3, 2015 15:22
Show Gist options
  • Save OriginUnknown/fc58f70a702d2bb5631e to your computer and use it in GitHub Desktop.
Save OriginUnknown/fc58f70a702d2bb5631e to your computer and use it in GitHub Desktop.
JavaScript OOP Design Patterns - Composite Pattern v2
<!doctype html>
<html lang="en">
<head>
<title>Composite pattern - 2</title>
</head>
<body>
<script type="text/javascript">
var db = (function () {
/*
* * Component is the base function containing the operation method {displayInfo}
* * common to both leaf and composite component objects
*/
var Component = function ( name ) {
if ( typeof(name) === 'string' ) {
var _name = name,
displayInfo = function () {
return _name;
};
return {
"displayInfo": displayInfo
}
} else {
throw new Error( "Unsupported Operation." );
}
},
Composite = function ( name ) {
var composite = Component( name ), children = [], nm = name,
_log = "",
traverse = function ( indent, node ) {
/*
* * Using the Array object's join() method, join() returns to the
* * _log variable a modified string of the node name with
* * dashes (--) appended to it as the chosen separator
* * i.e. "Root--Alternative--African" etc.
*/
_log += new Array( indent ++ ).join( "--" ) + node.displayInfo() + "\n";
if ( node.hasOwnProperty( 'getChildren' ) ) {//if the node has the children array...
var i = 0, len = node.getChildren().length;
for ( ; i < len; i ++ ) {
traverse( indent, node.getChildAt( i ) );
/*
* * ..it will call the traverse method in each child recursively.
* * Incidentally, the traverse method continues looping even if
* * the node is a leaf so long as it's parent still has children
* * to loop through. Else the traverse method is concluded.
*/
}
}
};
//addSong() returns a leaf object containing only the operation (displayInfo) method needed
composite.addSong = function ( component ) {
var _leaf = Component( component );
children.push( _leaf );
return _leaf;
};
//createDir returns a composite object containing the relevant properties associated with this object
composite.createDir = function ( component ) {
var _comp = Composite( component );
children.push( _comp );
return _comp;
};
composite.remove = function ( child ) {
var _parent = composite, _msg = "",
_children = _parent.getChildren(),
_len = _children.length,
i = 0, _node;
for ( ; i < _len; i ++ ) {
_node = _parent.getChildAt( i );
if ( _node.displayInfo() === child.displayInfo() ) {
_children.splice( i, 1 );
_msg = "Done!";
return _msg;
}
}
};
composite.getChildren = function () {
return children;
};
composite.getChildAt = function ( index ) {
return children[ index ];
};
composite.showFiles = function ( n ) {
var _parent = composite;
if ( ! arguments.length > 0 ) {
_log = "";//clear the previous message, if any, from the _log variable
traverse( 1, _parent );//log all files within the parent by default
return _log;
} else {
var _children = _parent.getChildren(),
_len = _children.length,
i = 0, _child;
for ( ; i < _len; i ++ ) {
_child = _parent.getChildAt( i );
//if n is either a child node of it's parent or the parent itself
if ( (_child.displayInfo() === n.displayInfo()) || (n.displayInfo() === _parent.displayInfo()) ) {
_log = "";//clear the previous message, if any, from the _log variable
traverse( 1, n );//logs a new message to the _log variable for the n arguments passed in
return _log;
}
}
}
};
return composite;
}, _root = Composite( "Root" );
return _root;
})();
//Root acts like the root parent for all our songs
var Root = db;
console.log( Root );
//Add two songs directly to the Root dir
var HappyUpHere = Root.addSong( "Happy Up Here" ),
MyMyMy = Root.addSong( "My My My" );
//Root's sub-directories -> test#1: Create directories using the createDir method
var Alternative = Root.createDir( "Alternative" ),
Trance = Root.createDir( "Trance" );
//Alternative dir - {sub dir}
var African = Alternative.createDir( "Afro Beats" );
//Alternative dir - {songs} -> test#2: Add songs to directories using the addSong method
var Eple = Alternative.addSong( "Eple" ),
Galvanize = Alternative.addSong( "Galvanize" ),
Trouble = Alternative.addSong( "Trouble" ),
Shiver = Alternative.addSong( "Shiver" );
//Alternative > African dir
var WakaWaka = African.addSong( "Waka Waka" ),
Asonto = African.addSong( "Asonto" ),
ChopYourDolla = African.addSong( "Chop Your Dolla" );
//Trance {sub dir}
var Electronic = Trance.createDir( "Electronic" ),
Dance = Trance.createDir( "Dance" );
//Trance dir - {songs}
var WideOpenSpace = Trance.addSong( "Wide Open Space" ),
Offshore = Trance.addSong( "Offshore" ),
DarkTrain = Trance.addSong( "Dark Train" );
//Trance > Electronic > {songs}
var Domination = Electronic.addSong( "Domination" ),
UnfinishedSympathy = Electronic.addSong( "Unfinished Sympathy" );
//Trance > Dance > {songs}
var MoveYourBody = Dance.addSong( "Move Your Body" ),
DrummerGetWicked = Dance.addSong( "Drummer Get Wicked" ),
Pride = Dance.addSong( "Pride {A deeper love}" );
//Print out everything (songs and directories) within the Root directory
console.log( Root.showFiles() );
//Print out everything (songs and directories) within the Alternative directory WITHOUT an argument
console.log( Alternative.showFiles() );
//Print out everything (songs and directories) within the Alternative directory WITH an argument
console.log( Alternative.showFiles( Alternative ) );
//Print out everything (songs and directories) within the African directory ONLY
console.log( Alternative.showFiles( African ) );
//Remove the African directory from the Alternative directory
console.log( Alternative.remove( African ) );//pass: returns "Done!"
/*
* * Print out everything within the Alternative directory after the African
* * directory has been removed
*/
console.log( Alternative.showFiles( African ) );//pass: returns undefined
/*
* * Print out everything within the Root directory after the African directory
* * has been removed
*/
console.log( Root.showFiles( Root ) );
//Test#10: Remove the song "My My My" from Root directory and print modified root directory
console.log( Root.remove( MyMyMy ) );
console.log( Root.showFiles() );
//Test#11: When an object is passed to the createDir method, it returns "Unsupported Operation."
//var BlackEyedPeas = Root.createDir({"name":"Black Eyed Peas"});//pass.
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment