Last active
August 29, 2015 14:23
-
-
Save OriginUnknown/2262ffd42a7ef6a65d84 to your computer and use it in GitHub Desktop.
JavaScript OOP Design Pattern - Builder Pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<title>Builder pattern</title> | |
</head> | |
<body> | |
<script type="text/javascript"> | |
//Builder pattern based on Tortilla Burrito and Tossed Salad Bar | |
var Tossed = (function () { | |
var self = {}; | |
/* | |
* * Builders - define the steps (aka signature methods) required for creating a Product. | |
* * Normally using a 'builder interface', each builder class will implement each signature method according to the specifications of the Product. | |
* * As JavaScript has no interfaces, every builder object uses the same method name | |
*/ | |
/* | |
* * buildTheGreek is the Builder that specifies how the greek option will be made. | |
* * Each builder has it's own way of building a salad or wrap but the steps to create | |
* * a salad or wrap are the same or every builder variant. | |
* * | |
* * NB: Array.join() method converts your array into a string; the optional separator | |
* * allows you to specify what character you want between each array item | |
*/ | |
buildTheGreek = function ( options ) { | |
var greekBuilderObj = { | |
"type" : "greek",//purely for logging purposes only | |
"selectYourBase" : function () { | |
return options.base; | |
}, | |
"selectYourProtein" : function () { | |
return options.protein.join(', '); | |
}, | |
"selectedYourDeli" : function () { | |
return options.deli.join(', '); | |
}, | |
"selectYourVeggies" : function () { | |
return options.veggies.join(', '); | |
}, | |
"selectYourDressing" : function () { | |
return options.dressing; | |
}, | |
"myOption" : options | |
}; | |
make( greekBuilderObj ); | |
}; | |
buildTheChipotle = function ( options ) { | |
var chipotleBuilderObj = { | |
"type" : "chipotle",//purely for logging purposes only | |
"selectYourBase" : function () { | |
return options.base; | |
}, | |
"selectYourProtein" : function () { | |
return options.protein.join(', '); | |
}, | |
"selectedYourDeli" : function () { | |
return options.deli.join(', '); | |
}, | |
"selectYourVeggies" : function () { | |
return options.veggies.join(', '); | |
}, | |
"selectYourDressing" : function () { | |
return options.dressing; | |
}, | |
"myOption" : options | |
}; | |
make( chipotleBuilderObj ); | |
}; | |
buildTheChickenBaconAvocado = function ( options ) { | |
var chickenBaconAvocadoBuilderObj = { | |
"type" : "Chicken, Bacon and Avocado",//purely for logging purposes only | |
"selectYourBase" : function () { | |
return options.base; | |
}, | |
"selectYourProtein" : function () { | |
return options.protein.join(', '); | |
}, | |
"selectedYourDeli" : function () { | |
return options.deli.join(', '); | |
}, | |
"selectYourVeggies" : function () { | |
return options.veggies.join(', '); | |
}, | |
"selectYourDressing" : function () { | |
return options.dressing; | |
}, | |
"myOption" : options | |
}; | |
make( chickenBaconAvocadoBuilderObj ); | |
}; | |
buildCustom = function ( options ) { | |
var customBuilderObj = { | |
"type" : "Custom",//purely for logging purposes only | |
"selectYourBase" : function () { | |
return options.base; | |
}, | |
"selectYourProtein" : function () { | |
return options.protein.join(', '); | |
}, | |
"selectedYourDeli" : function () { | |
return options.deli.join(', '); | |
}, | |
"selectYourVeggies" : function () { | |
return options.veggies.join(', '); | |
}, | |
"selectYourDressing" : function () { | |
return options.dressing; | |
}, | |
"myOption" : options | |
}; | |
make( customBuilderObj ); | |
}; | |
/* | |
* * Director - constructs the Product and returns it in its entirety. Under OOP, the Director will execute the signature methods defined in the 'builder interface' | |
* * once it has a builder object (hence the use of the same method names as the builder objects). The Director purpose is only to execute the builder, it isn't | |
* * interested in how each signature method is implemented | |
*/ | |
/* | |
* * The make method creates the salad or wrap order by executing the steps required for its construction. Ultimately it will return the finished product | |
* * which a salad or wrap raady to serve the customer. Bon appetite! | |
*/ | |
make = function ( options ) { | |
var builder = options, msg = ""; | |
var makeMyOrder = (function () { | |
console.log( builder.selectYourBase() ); | |
console.log( builder.selectYourProtein() ); | |
console.log( builder.selectedYourDeli() ); | |
console.log( builder.selectYourVeggies() ); | |
console.log( builder.selectYourDressing() ); | |
})(); | |
var myFinishedProduct = (function () { | |
msg = "Your " + builder.type + " base selection is " + builder.myOption.base + ".\n"; | |
msg += "Your " + builder.type + " protein selection is " + builder.myOption.protein.join(', ') + ".\n"; | |
msg += "Your " + builder.type + " deli selection is " + builder.myOption.deli.join(', ') + ".\n"; | |
msg += "Your " + builder.type + " veggies selection is " + builder.myOption.veggies.join(', ') + ".\n"; | |
msg += "Your chosen " + builder.type + " dressing is " + builder.myOption.dressing + ".\n"; | |
return msg; | |
})(); | |
console.log( myFinishedProduct ); | |
return myFinishedProduct; | |
}; | |
/* | |
* * Products - these are the components (ingredients) required to build each Product (salad or wrap) | |
* * Only the Products are exposed to the customer | |
*/ | |
/* | |
* * Greek order is a Product that contains the ingredients required to create a greek salad or wrap. The customer can order the default greek salad | |
* * or customise it via the options object which will either add to or remove ingredients from the greek order | |
*/ | |
self.greek = function ( options ) { | |
var ingredients = {//default ingredients | |
"base" : "Lettuce and Spinach", | |
"protein" : [ "No protein" ], | |
"deli" : [ "Houmous", "Feta" ], | |
"veggies" : [ "Olives", "Tomatoes", "Mixed peppers", "Cucumber", "Red onions" ], | |
"dressing" : "Oregano and Balsamic vinegarette" | |
}, greekBuilder, myGreekOption; | |
if ( options ) {//custom greek option | |
myGreekOption = { | |
"base" : (function () { | |
return (options.hasOwnProperty( 'base' )) ? options.base : ingredients.base | |
})(), | |
"protein" : (function () { | |
return (options.hasOwnProperty( 'protein' )) ? options.protein : ingredients.protein | |
})(), | |
"deli" : (function () { | |
return (options.hasOwnProperty( 'deli' )) ? options.deli : ingredients.deli | |
})(), | |
"veggies" : (function () { | |
return (options.hasOwnProperty( 'veggies' )) ? options.veggies : ingredients.veggies | |
})(), | |
"dressing" : (function () { | |
return (options.hasOwnProperty( 'dressing' )) ? options.dressing : ingredients.dressing | |
})() | |
}; | |
greekBuilder = buildTheGreek( myGreekOption ); | |
} else {//return default greek ingredients | |
myGreekOption = ingredients; | |
greekBuilder = buildTheGreek( myGreekOption ); | |
} | |
}; | |
self.chipotle = function ( options ) { | |
var ingredients = { | |
"base" : "Kale and cous cous", | |
"protein" : [ "Chicken breast" ], | |
"deli" : [ "Avocado", "Cheddar" ], | |
"veggies" : [ "Mixed beans", "Jalapenos", "coriander", "Tomato Salsa", "Tortilla chips" ], | |
"dressing" : "Ranch dressing" | |
}, chipotleBuilder, myChipotleOption; | |
if ( options ) {//custom chipotle option | |
myChipotleOption = { | |
"base" : (function () { | |
return (options.hasOwnProperty( 'base' )) ? options.base : ingredients.base | |
})(), | |
"protein" : (function () { | |
return (options.hasOwnProperty( 'protein' )) ? options.protein : ingredients.protein | |
})(), | |
"deli" : (function () { | |
return (options.hasOwnProperty( 'deli' )) ? options.deli : ingredients.deli | |
})(), | |
"veggies" : (function () { | |
return (options.hasOwnProperty( 'veggies' )) ? options.veggies : ingredients.veggies | |
})(), | |
"dressing" : (function () { | |
return (options.hasOwnProperty( 'dressing' )) ? options.dressing : ingredients.dressing | |
})() | |
}; | |
chipotleBuilder = buildTheChipotle( myChipotleOption ); | |
} else {//return default chipotle option | |
myChipotleOption = ingredients; | |
chipotleBuilder = buildTheChipotle( myChipotleOption ); | |
} | |
}; | |
self.chickenBaconAvocado = function ( options ) { | |
var ingredients = { | |
"base" : "Supergrains", | |
"protein" : [ "Chicken breast", "Bacon" ], | |
"deli" : [ "Avocado" ], | |
"veggies" : [ "New Potatoes", "Tomatoes", "Pine nuts" ], | |
"dressing" : "French dressing" | |
}, chickenBaconAvocadoBuilder, myChickenBaconAvocadoOption; | |
if ( options ) {//custom chicken Bacon and Avocado option | |
myChickenBaconAvocadoOption = { | |
"base" : (function () { | |
return (options.hasOwnProperty( 'base' )) ? options.base : ingredients.base | |
})(), | |
"protein" : (function () { | |
return (options.hasOwnProperty( 'protein' )) ? options.protein : ingredients.protein | |
})(), | |
"deli" : (function () { | |
return (options.hasOwnProperty( 'deli' )) ? options.deli : ingredients.deli | |
})(), | |
"veggies" : (function () { | |
return (options.hasOwnProperty( 'veggies' )) ? options.veggies : ingredients.veggies | |
})(), | |
"dressing" : (function () { | |
return (options.hasOwnProperty( 'dressing' )) ? options.dressing : ingredients.dressing | |
})() | |
}; | |
chickenBaconAvocadoBuilder = buildTheChickenBaconAvocado( myChickenBaconAvocadoOption ); | |
} else {//return default chicken Bacon and Avocado option | |
myChickenBaconAvocadoOption = ingredients; | |
chickenBaconAvocadoBuilder = buildTheChickenBaconAvocado( myChickenBaconAvocadoOption ); | |
} | |
}; | |
self.createYourOwn = function ( options ) { | |
if ( ! options ) { | |
throw new Error( "Please select the relevant ingredients to create your own salad or wrap" ); | |
} else { | |
var customBuilder, myCustomOption; | |
myCustomOption = { | |
"base" : (function () { | |
return (options.hasOwnProperty( 'base' )) ? options.base : "no base" | |
})(), | |
"protein" : (function () { | |
return (options.hasOwnProperty( 'protein' )) ? options.protein : [ "no protein" ]; | |
})(), | |
"deli" : (function () { | |
return (options.hasOwnProperty( 'deli' )) ? options.deli : [ "no deli" ]; | |
})(), | |
"veggies" : (function () { | |
return (options.hasOwnProperty( 'veggies' )) ? options.veggies : [ "no veggies" ]; | |
})(), | |
"dressing" : (function () { | |
return (options.hasOwnProperty( 'dressing' )) ? options.dressing : "no dressing" | |
})() | |
}; | |
customBuilder = buildCustom( myCustomOption ); | |
} | |
}; | |
return self; | |
})(); | |
//greek orders | |
var mickeysGreek = Tossed.greek();//default greek order | |
var janeysGreek = Tossed.greek( {//custom greek order with cous cous over lettuce and spinach for the base, feta only and NO red onions and cucumber | |
"base" : "Cous Cous", | |
"deli" : [ "Feta" ], | |
"veggies" : [ "Tomatoes", "Mixed peppers", "Cucumber" ] | |
} ); | |
//chipotle orders | |
var frankysChipotle = Tossed.chipotle();//default chipotle order | |
var ralphsChipotle = Tossed.chipotle( {//custom chipotle order WITHOUT jalepenos and dressing | |
"protein" : [ "falafel" ], | |
"deli" : [ "Avocado" ], | |
"veggies" : [ "Mixed beans", "coriander", "Tomato Salsa", "Tortilla chips" ], | |
"dressing" : "No dressing" | |
} ); | |
//Chicken, Bacon and Avocado orders | |
var hannahsCBA = Tossed.chickenBaconAvocado();//default chicken, bacon and avocado order | |
var ginnasCBA = Tossed.chickenBaconAvocado( {//custom chicken, bacon and avocado with added houmous and sweet chilli dressing instead of french dressing | |
"deli" : [ "Avocado", "Houmous" ], | |
"dressing" : "Sweet chilli" | |
} ); | |
//test - create your own option {CYO} | |
var charliesCreateYourOwn = Tossed.createYourOwn( {//returns a custom made wrap with all the trimmings | |
"base" : "Wrap", | |
"protein" : [ "Chicken goujons", "Halloumi" ], | |
"deli" : [ "Mozzarella", "Sweet potato" ], | |
"veggies" : [ "Carrots", "Olives", "Spring onion" ], | |
"dressing" : "Sweet chilli" | |
} ); | |
var lizzysCreateYourOwn = Tossed.createYourOwn( {//returns a custom salad with not so many trimmings included | |
"base" : "Brown rice", | |
"deli" : [ "Cheddar" ], | |
"veggies" : [ "Pine nuts", "Broccoli" ] | |
} ); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment