Flyweight Design Pattern in PHP

1. Definition

The Flyweight Design Pattern is a structural pattern that uses sharing to support large numbers of fine-grained objects efficiently. It aims to minimize memory usage by sharing as much data as possible with other similar objects.

2. Problem Statement

When working with numerous almost identical objects that consume a lot of memory, creating a new object for each can be inefficient and could slow down the application.

3. Solution

The Flyweight pattern reduces the burden on memory by sharing objects. Instead of creating new instances, it reuses objects that are already created if they match the needed criteria.

4. Real-World Use Cases

1. Text editors that deal with character rendering. Each character can be a flyweight with shared data like font and size.

2. Online gaming platforms where many users may have the same avatar, weapon, or costume.

3. Any scenario where large numbers of similar objects can be reduced to shared instances to save resources.

5. Implementation Steps

1. Create a Flyweight interface that declares a method for receiving and acting on extrinsic states.

2. Implement the ConcreteFlyweight class that implements the Flyweight interface and stores intrinsic state.

3. Create a FlyweightFactory class that creates and manages flyweight objects and ensures sharing of flyweights.

6. Implementation in PHP

<?php
// Flyweight interface
interface Flyweight {
    public function operation(string $extrinsicState): void;
}
// ConcreteFlyweight
class ConcreteFlyweight implements Flyweight {
    private $intrinsicState;
    public function __construct(string $intrinsicState) {
        $this->intrinsicState = $intrinsicState;
    }
    public function operation(string $extrinsicState): void {
        echo "Intrinsic State: " . $this->intrinsicState . " - Extrinsic State: " . $extrinsicState . "\n";
    }
}
// FlyweightFactory
class FlyweightFactory {
    private $flyweights = [];
    public function getFlyweight(string $key): Flyweight {
        if (!isset($this->flyweights[$key])) {
            $this->flyweights[$key] = new ConcreteFlyweight($key);
        }
        return $this->flyweights[$key];
    }
}
// Client code
$factory = new FlyweightFactory();
$flyweight1 = $factory->getFlyweight('A');
$flyweight2 = $factory->getFlyweight('B');
$flyweight1->operation('first');
$flyweight2->operation('second');
?>

Output:

Intrinsic State: A - Extrinsic State: first
Intrinsic State: B - Extrinsic State: second

Explanation:

In the example, we first define a Flyweight interface and a ConcreteFlyweight class. The concrete class maintains intrinsic data (internal state), while the operations it exposes can utilize extrinsic data (external state).

The FlyweightFactory ensures that objects are shared: it only creates a new flyweight if one with the desired intrinsic state doesn't exist.

When the client retrieves two flyweights from the factory and operates on them, it demonstrates how these objects can handle intrinsic and extrinsic states.

7. When to use?

The Flyweight Pattern should be used when:

1. An application uses a large number of objects, which makes a significant impact on memory.

2. Object's intrinsic state can be shared among multiple instances.

3. Once externalized, an object's extrinsic state can be passed in by the client when necessary.


Comments