The Flyweight pattern is a structural design pattern that reduces memory usage and enhances performance by sharing objects. It is suitable for scenarios with a large number of similar objects, and by sharing the common state of these objects, it helps save memory and reduce the overhead of object creation and destruction.
The core idea behind the Flyweight pattern is to separate objects into two parts: internal state (inherent properties) and external state (extrinsic properties). Internal state remains constant and can be shared among multiple objects, while external state is variable and typically determined by the object's environment.
By sharing internal states, the number of objects can be reduced, which significantly cuts down memory consumption. External states are dynamically passed into the object and modified during use.
The Flyweight pattern is valuable in the following situations:
When a system contains many similar objects, the Flyweight pattern can be used to share internal states, thus reducing memory usage.
If an object's properties can be categorized into internal and external states, internal states can be shared, while external states are determined by the environment.
To implement the Flyweight pattern in PHP, follow these basic steps:
First, create a Flyweight Factory, which manages and provides access to shared Flyweight objects.
class FlyweightFactory {
private $flyweights = [];
public function getFlyweight($key) {
if (!isset($this->flyweights[$key])) {
$this->flyweights[$key] = new ConcreteFlyweight($key);
}
return $this->flyweights[$key];
}
}
Next, define the Flyweight interface.
interface Flyweight {
public function operation();
}
Then, create the concrete Flyweight objects that implement shared internal and external states.
class ConcreteFlyweight implements Flyweight {
private $key;
public function __construct($key) {
$this->key = $key;
}
public function operation() {
// specific operation logic
}
}
Consider a game development scenario where a character manager needs to handle many character objects. Some character attributes, such as job and skills, are constant, while others, like position and health, change during gameplay.
In this case, the job can be shared as the internal state, while position and health are passed as external states.
class Character {
private $job;
private $position;
private $hp;
public function __construct($job) {
$this->job = $job;
}
public function setPosition($x, $y) {
$this->position = "($x, $y)";
}
public function setHP($hp) {
$this->hp = $hp;
}
public function display() {
echo "Job: {$this->job}, Position: {$this->position}, HP: {$this->hp}";
}
}
Using the Flyweight pattern allows us to reduce the number of character objects, improving memory efficiency and system performance.
$factory = new FlyweightFactory();
$character1 = $factory->getFlyweight('Warrior');
$character1->setPosition(10, 20);
$character1->setHP(100);
$character1->display();
$character2 = $factory->getFlyweight('Mage');
$character2->setPosition(30, 40);
$character2->setHP(80);
$character2->display();
Output:
Job: Warrior, Position: (10, 20), HP: 100
Job: Mage, Position: (30, 40), HP: 80
The output shows that the shared internal state (job) is the same, while the external states (position and HP) differ.