Sobes.tech
Middle+

What is the Flyweight design pattern?

sobes.tech AI

Answer from AI

The Flyweight is a structural design pattern that allows saving memory by sharing state between multiple objects. It is used when an application has many similar objects, and most of them share the same state.

The pattern divides the object's state into two parts:

  1. Intrinsic State: The state shared by all objects and independent of their context. It is stored inside the Flyweight and shared among many clients.
  2. Extrinsic State: The state dependent on the context in which the object is used. It is passed to the Flyweight's methods by the client as needed.

Main components of the pattern:

  • Flyweight: An interface or abstract class declaring methods that accept external state as a parameter.
  • ConcreteFlyweight: A class implementing the Flyweight interface and storing the intrinsic state.
  • FlyweightFactory: A class managing the creation and caching of ConcreteFlyweight objects. It checks if a Flyweight with the given intrinsic state already exists and returns it, or creates a new one.
  • Client: An object that uses Flyweights, storing external state and invoking Flyweight methods, passing this state.

Example of use: a text editor. Characters (letters, digits) can be Flyweights. The internal state of a character is the character itself (e.g., 'A'). The external state includes its position, color, font size. Instead of creating a new object for each character in the document, only one object is created for each unique character, and its formatting characteristics are applied "externally".

import json // Example import, although not used in this code

// Flyweight interface
class Flyweight:
    def operation(self, extrinsic_state): // Method accepting external state
        pass

// ConcreteFlyweight
class ConcreteFlyweight(Flyweight):
    def __init__(self, intrinsic_state):
        self._intrinsic_state = intrinsic_state // Intrinsic state

    def operation(self, extrinsic_state):
        // Simulate operation considering external state
        print(f"ConcreteFlyweight: Intrinsic state - {self._intrinsic_state}, Extrinsic state - {extrinsic_state}")

// FlyweightFactory
class FlyweightFactory:
    _flyweights = {} // Cache of Flyweights

    def get_flyweight(self, intrinsic_state):
        if intrinsic_state not in self._flyweights:
            print(f"FlyweightFactory: Creating a new flyweight for {intrinsic_state}")
            self._flyweights[intrinsic_state] = ConcreteFlyweight(intrinsic_state) // Create new Flyweight
        else:
            print(f"FlyweightFactory: Reusing existing flyweight for {intrinsic_state}")
        return self._flyweights[intrinsic_state] // Return existing or new Flyweight

Advantages:

  • Reduces memory consumption by sharing common state.
  • Decreases the number of objects created.

Disadvantages:

  • Complicates code due to state sharing.
  • Requires passing external state with each method call.
  • May be redundant if the number of objects is small or their states vary greatly.