Skip to content

Instantly share code, notes, and snippets.

@OriginUnknown
Last active August 29, 2015 14:23
Show Gist options
  • Save OriginUnknown/2262ffd42a7ef6a65d84 to your computer and use it in GitHub Desktop.
Save OriginUnknown/2262ffd42a7ef6a65d84 to your computer and use it in GitHub Desktop.
JavaScript OOP Design Pattern - Builder Pattern
<!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