Created
July 21, 2019 22:20
-
-
Save JasonBBelcher/d34a26bf3b9ca01f0e2334e5ecaa5c68 to your computer and use it in GitHub Desktop.
Composing with factory functions
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
// Composition over inheritance with Factory functions | |
// No classes were hurt in the making of this file. | |
// single factory functions utilizing higher order functions | |
// to pass arguments without returning the object at same time | |
function synthFactory(manufacturer, type, model) { | |
return function() { | |
return { | |
instrument: "synth", | |
type, | |
manufacturer, | |
model, | |
displayProperties | |
}; | |
}; | |
} | |
function guitarFactory(manufacturer, type, model) { | |
return function() { | |
return { | |
instrument: "guitar", | |
type, | |
manufacturer, | |
model, | |
displayProperties | |
}; | |
}; | |
} | |
function pianoFactory(manufacturer, type, model) { | |
return function() { | |
return { | |
instrument: "piano", | |
type, | |
manufacturer, | |
model, | |
displayProperties | |
}; | |
}; | |
} | |
function drumsetFactory(manufacturer, type, model) { | |
return function() { | |
return { | |
instrument: "drumset", | |
type, | |
manufacturer, | |
model, | |
displayProperties | |
}; | |
}; | |
} | |
/* | |
bandFactory takes in a list of factories as args and loops over | |
them and calls each one, assigns each one a name based on | |
the manufacturer name. Lastly it returns the | |
composed parent object with each instrument object attached | |
*/ | |
function bandFactory(...factories) { | |
let band = {}; | |
factories.forEach(factory => { | |
band[factory().manufacturer] = factory(); | |
}); | |
return band; | |
} | |
// this will always point to the right object because this is determined | |
// by it's call site not it's location. | |
function displayProperties() { | |
return `I am a ${this.type} ${this.instrument} made by ${ | |
this.manufacturer | |
} and my model is: ${this.model}`; | |
} | |
// lets use the factory of factories. | |
const theBandInstruments = bandFactory( | |
synthFactory("Moog", "semi-modular", "mother-32"), | |
guitarFactory("Fender", "electric", "telecaster"), | |
pianoFactory("Steinway", "grand", "model S"), | |
drumsetFactory("Gretsch", "small", "GS1") | |
); | |
// when called prints the passed in composed factory of factories | |
function printTheBand(band) { | |
if (band) { | |
Object.keys(band).forEach(key => { | |
console.log(band[key].displayProperties()); | |
}); | |
} else { | |
console.error("***please pass in a band factory***"); | |
} | |
} | |
printTheBand(theBandInstruments); | |
// create individual instrument factories | |
const d50 = synthFactory("Roland", "Linear Arithmetic", "D-50")(); | |
const d70 = synthFactory("Roland", "Linear Arithmetic", "D-70")(); | |
// call individual methods | |
console.log(d50.displayProperties()); | |
console.log(d70.displayProperties()); | |
// dynamically creates any kind of instrument object not just a specific type | |
function instrumentFactory(name, brand) { | |
name = name.replace(/ /g, "").toLowerCase(); | |
brand = brand.replace(/ /g, "").toLowerCase(); | |
return function() { | |
return { | |
[name]: { brand, name } | |
}; | |
}; | |
} | |
function findAllInstrumentsByProperty(prop) { | |
prop = prop.replace(/ /g, "").toLowerCase(); | |
instrumentsByProp = []; | |
const regex = new RegExp(prop + ".*"); | |
// loop over each key and see if the prop being searched for | |
// is the name or brand. | |
Object.keys(this).forEach(instrument => { | |
if (this[instrument].brand === prop) { | |
instrumentsByProp.push(instrument); | |
} | |
// if it's the name we match the key word and anything after it | |
// guitar, guitar1, guitar2 etc would match passing in "guitar" | |
if (this[instrument].name.match(regex)) { | |
instrumentsByProp.push(instrument); | |
} | |
}); | |
// return the basic stats for the prop searched for. | |
return { [prop]: instrumentsByProp, count: instrumentsByProp.length }; | |
} | |
// factory of factories takes in instrument factories and creates an inventory of all the instruments | |
// in an imaginary music store. This time merge all the objects returned into the inventory object | |
function instrumentInventory(...factories) { | |
let inventory = {}; | |
factories.forEach(factory => { | |
Object.assign(inventory, factory()); | |
}); | |
inventory.findAllInstrumentsByProperty = findAllInstrumentsByProperty; | |
return inventory; | |
} | |
const inventory = instrumentInventory( | |
instrumentFactory("Tenor Sax", "Yamaha"), | |
instrumentFactory("guitar", "Gibson"), | |
instrumentFactory("Guitar2", "Gibson"), | |
instrumentFactory("Guitar3", "Gibson"), | |
instrumentFactory("Guitar4", "Fender"), | |
instrumentFactory("Guitar5", "Martin"), | |
instrumentFactory("drumkit", "Yamaha"), | |
instrumentFactory("keyboard1", "moog"), | |
instrumentFactory("keyboard2", "roland"), | |
instrumentFactory("keyboard3", "korg"), | |
instrumentFactory("keyboard4", "Dave Smith"), | |
instrumentFactory("drumkit2", "Gretsch"), | |
instrumentFactory("Bass Guitar", "Fender") | |
); | |
console.log(inventory.findAllInstrumentsByProperty("Yamaha")); | |
console.log(inventory.findAllInstrumentsByProperty("Yamaha")); | |
console.log(inventory.findAllInstrumentsByProperty("gibson")); | |
console.log(inventory.findAllInstrumentsByProperty("guitar")); | |
console.log(inventory.findAllInstrumentsByProperty("bass")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment