Flyweight Design Pattern in JavaScript

1. Definition

The Flyweight Design Pattern is a structural pattern that aims to use shared objects to efficiently manage large numbers of fine-grained objects, minimizing memory usage. It does so by separating intrinsic state (shared) from extrinsic state (external and unique).

2. Problem Statement

Imagine you are building a word processor, and each character in the document is represented by a separate object. If you have a long document, this would result in a huge number of character objects leading to significant memory usage.

3. Solution

Instead of creating individual objects for each character, you can create a shared object for each unique character and reuse it. The intrinsic state (e.g., character value) can be stored in these shared objects, while the extrinsic state (e.g., position in the document) can be stored externally.

4. Real-World Use Cases

1. Text editors: Representing each unique character with a flyweight object.

2. Graphic tools: Using flyweight objects for shared components like colors or shapes.

3. Game development: Representing shared game entities like trees or stones using flyweights.

5. Implementation Steps

1. Identify the shared state (intrinsic) and the external state (extrinsic).

2. Create a flyweight factory that manages the creation and sharing of flyweight objects.

3. Ensure that the client code uses the factory to create/retrieve flyweight objects.

6. Implementation in JavaScript

// Flyweight class
function Character(value) {
    this.value = value;
}
Character.prototype.display = function(position) {
    console.log(`Character ${this.value} is displayed at position ${position}.`);
};
// Flyweight Factory
function CharacterFactory() {
    this.characters = {};
}
CharacterFactory.prototype.getCharacter = function(value) {
    if (!this.characters[value]) {
        this.characters[value] = new Character(value);
    }
    return this.characters[value];
};
// Client Code
const factory = new CharacterFactory();
const characterA = factory.getCharacter('A');
const characterB = factory.getCharacter('B');
characterA.display(1);  // position 1
characterB.display(2);  // position 2
characterA.display(3);  // position 3

Output:

Character A is displayed at position 1.
Character B is displayed at position 2.
Character A is displayed at position 3.

Explanation:

1. The Character class represents a flyweight object. The intrinsic state is the value of the character.

2. The CharacterFactory acts as a manager, ensuring that each unique character is only created once.

3. In the client code, even though we "retrieve" character A twice, it's the same shared object. The position (extrinsic state) is passed externally.

7. When to use?

Use the Flyweight pattern when:

1. You have a large number of objects which makes it costly in terms of memory.

2. Most of the object state can be made extrinsic.

3. Once the external state is removed, many groups of distinct objects can be replaced by relatively few shared objects.


Comments