Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Created May 12, 2012 20:19
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save addyosmani/2668755 to your computer and use it in GitHub Desktop.
Save addyosmani/2668755 to your computer and use it in GitHub Desktop.
The Flyweight pattern
// Flyweight.js - Copyright Addy Osmani, 2012.
// Consider public domain
// My implementation in JS of this:
// http://en.wikipedia.org/wiki/Flyweight_pattern
// Simulate pure virtual inheritance/'implement' keyword for JS
Function.prototype.implementsFor = function (parentClassOrObject) {
if (parentClassOrObject.constructor == Function) {
// Normal Inheritance
this.prototype = new parentClassOrObject;
this.prototype.constructor = this;
this.prototype.parent = parentClassOrObject.prototype;
} else {
// Pure Virtual Inheritance
this.prototype = parentClassOrObject;
this.prototype.constructor = this;
this.prototype.parent = parentClassOrObject;
}
return this;
}
// Flyweight object
var CoffeeOrder = {
// Interfaces
serveCoffee: function (context) {},
getFlavor: function () {}
};
// ConcreteFlyweight object that creates ConcreteFlyweight
function CoffeeFlavor(newFlavor) {
var flavor = newFlavor;
// If an interface has been defined for a feature
// implement the feature
if (typeof this.getFlavor === "function") {
this.getFlavor = function () {
return flavor;
};
}
if (typeof this.serveCoffee === "function") {
this.serveCoffee = function (context) {
console.log("Serving Coffee flavor " + flavor + " to table number " + context.getTable());
};
}
}
// Implement interface for CoffeeOrder
CoffeeFlavor.implementsFor(CoffeeOrder);
// Handle table numbers for a coffee order
function CoffeeOrderContext(tableNumber) {
var tableNumber = tableNumber;
return {
getTable: function () {
return tableNumber;
}
}
}
//FlyweightFactory object
function CoffeeFlavorFactory() {
var flavors = [];
return {
getCoffeeFlavor: function (flavorName) {
var flavor = flavors[flavorName];
if (flavor === undefined) {
flavor = new CoffeeFlavor(flavorName);
flavors.push([flavorName, flavor]);
}
return flavor;
},
getTotalCoffeeFlavorsMade: function () {
return flavors.length;
}
}
}
// Sample usage:
// testFlyweight()
function testFlyweight() {
// The flavors ordered.
var flavors = new CoffeeFlavor(),
// The tables for the orders.
tables = new CoffeeOrderContext(),
// Number of orders made
ordersMade = 0,
// The CoffeeFlavorFactory instance
flavorFactory;
function takeOrders(flavorIn, table) {
flavors[ordersMade] = flavorFactory.getCoffeeFlavor(flavorIn);
tables[ordersMade++] = new CoffeeOrderContext(table);
}
flavorFactory = new CoffeeFlavorFactory();
takeOrders("Cappuccino", 2);
takeOrders("Cappuccino", 2);
takeOrders("Frappe", 1);
takeOrders("Frappe", 1);
takeOrders("Xpresso", 1);
takeOrders("Frappe", 897);
takeOrders("Cappuccino", 97);
takeOrders("Cappuccino", 97);
takeOrders("Frappe", 3);
takeOrders("Xpresso", 3);
takeOrders("Cappuccino", 3);
takeOrders("Xpresso", 96);
takeOrders("Frappe", 552);
takeOrders("Cappuccino", 121);
takeOrders("Xpresso", 121);
for (var i = 0; i < ordersMade; ++i) {
flavors[i].serveCoffee(tables[i]);
}
console.log(" ");
console.log("total CoffeeFlavor objects made: " + flavorFactory.getTotalCoffeeFlavorsMade());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment