Design patterns: Flyweight
The Flyweight Pattern is a structural pattern used to reduce memory consumption and improve efficiency in applications that have to manage a large number of similar objects. The core idea is to share common objects (flyweights) across multiple entities, avoiding unnecessary duplication. The immutable “flyweight” objects are shared, while the variable parts are managed separately.
Characteristics of the Flyweight pattern
- Reduced memory usage: It drastically reduces the amount of memory used by sharing, across multiple entities, the objects that have common, immutable properties.
- Efficiency: The pattern improves efficiency when large volumes of objects are created and managed, especially in contexts where the objects differ from one another only in minor ways.
- Object reuse: It makes it easier to reuse similar objects, minimizing the need to recreate the same data multiple times within the system.
- Separation of intrinsic and extrinsic state: The intrinsic state (immutable and shared) is kept separate from the extrinsic state (instance-specific). This allows objects to be managed more efficiently.
- Maintainability: The code is more maintainable and readable, because it centralizes the creation of similar objects, reducing the system’s complexity.
Use Case
Suppose we have to manage a large map of characters in a game, where each character has an icon but little variable information. Instead of creating a new instance for every single character, we can use the Flyweight Pattern to share icons among all similar characters.
PHP Code
// Flyweight - Shared object
class CharacterIcon {
private $icon; // Intrinsic state (shared)
public function __construct($icon) {
$this->icon = $icon;
}
public function render($x, $y) {
echo "Rendering icon '{$this->icon}' at position ($x, $y)\n";
}
}
// Flyweight Factory - Manages object sharing
class CharacterIconFactory {
private $icons = [];
public function getIcon($icon) {
if (!isset($this->icons[$icon])) {
$this->icons[$icon] = new CharacterIcon($icon);
}
return $this->icons[$icon];
}
}
// Client - Uses the flyweight objects with extrinsic state
class Game {
private $iconFactory;
public function __construct() {
$this->iconFactory = new CharacterIconFactory();
}
public function addCharacter($icon, $x, $y) {
$characterIcon = $this->iconFactory->getIcon($icon);
$characterIcon->render($x, $y); // Extrinsic state: the character's position
}
}
// Usage
$game = new Game();
$game->addCharacter('knight', 10, 20);
$game->addCharacter('knight', 15, 25);
$game->addCharacter('dragon', 30, 40);
$game->addCharacter('knight', 50, 60);
Explanation
- CharacterIcon represents the intrinsic (immutable) state that is shared among all characters of the same type.
- CharacterIconFactory manages the creation and sharing of CharacterIcon objects to avoid creating duplicates.
- Game manages the creation of characters, assigning them icons and placing them on the map. The extrinsic state (position) is variable and not shared.
Conclusion
The Flyweight Pattern is ideal when you’re dealing with a large number of similar objects that share many common properties, enabling significant memory savings and improving the application’s performance.