Skip to content

Instantly share code, notes, and snippets.

@JasonBBelcher
Created July 21, 2019 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JasonBBelcher/d34a26bf3b9ca01f0e2334e5ecaa5c68 to your computer and use it in GitHub Desktop.
Save JasonBBelcher/d34a26bf3b9ca01f0e2334e5ecaa5c68 to your computer and use it in GitHub Desktop.
Composing with factory functions
// 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