Skip to main content

JavaScript Example

/**
* The Flyweight stores a common portion of the state (also called intrinsic
* state) that belongs to multiple real business entities. The Flyweight accepts
* the rest of the state (extrinsic state, unique for each entity) via its
* method parameters.
*/
class Flyweight {
constructor(sharedState) {
this.sharedState = sharedState;
}

operation(uniqueState) {
const s = JSON.stringify(this.sharedState);
const u = JSON.stringify(uniqueState);
console.log(`Flyweight: Displaying shared (${s}) and unique (${u}) state.`);
}
}

module.exports = Flyweight;
const Flyweight = require("./Flyweight");

/**
* The Flyweight Factory creates and manages the Flyweight objects. It ensures
* that flyweights are shared correctly. When the client requests a flyweight,
* the factory either returns an existing instance or creates a new one, if it
* doesn't exist yet.
*/
class FlyweightFactory {
constructor(initialFlyweights) {
this.flyweights = {};
for (const state of initialFlyweights) {
this.flyweights[this.getKey(state)] = new Flyweight(state);
}
}

// Returns a Flyweight's string hash for a given state.
getKey(state) {
return state.join("_");
}

// Returns an existing Flyweight with a given state or creates a new one.
getFlyweight(sharedState) {
const key = this.getKey(sharedState);

if (!(key in this.flyweights)) {
console.log(
"FlyweightFactory: Can't find a flyweight, creating new one."
);
this.flyweights[key] = new Flyweight(sharedState);
} else {
console.log("FlyweightFactory: Reusing existing flyweight.");
}

return this.flyweights[key];
}

listFlyweights() {
const count = Object.keys(this.flyweights).length;
console.log(`\nFlyweightFactory: I have ${count} flyweights:`);
for (const key in this.flyweights) {
console.log(key);
}
}
}

module.exports = FlyweightFactory;
const FlyweightFactory = require("./FlyweightFactory");

/**
* The client code usually creates a bunch of pre-populated flyweights in the
* initialization stage of the application.
*/
const factory = new FlyweightFactory([
["Chevrolet", "Camaro2018", "pink"],
["Mercedes Benz", "C300", "black"],
["Mercedes Benz", "C500", "red"],
["BMW", "M5", "red"],
["BMW", "X6", "white"],
// ...
]);
factory.listFlyweights();

// ...

function addCarToPoliceDatabase(ff, plates, owner, brand, model, color) {
console.log("\nClient: Adding a car to database.");
const flyweight = ff.getFlyweight([brand, model, color]);

// The client code either stores or calculates extrinsic state and passes it
// to the flyweight's methods.
flyweight.operation([plates, owner]);
}

addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "M5", "red");

addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "X1", "red");

factory.listFlyweights();