Flyweight pattern shares basic object resources to generate a large number of objects efficiently. Flyweight pattern is used to reduce memory footprint.
This article demonstrates Flyweight pattern implementations in PHP. Check the implementation details and examples.
Implementation
Here is how to implement the Flyweight pattern-
- Create item class, of which we want to generate a large number of objects. This can be an existing class.
- Create a class to be used as the factory/generator of the item objects. This class holds a list of item objects separated by some type/category/block.
- Create static method in the factory to generate item object. If an item object of the same type/category/block already exists then return that, else create one and return that.
Here is a simple example of Flyweight pattern implement in PHP:
<?php
// Flyweight pattern implementation in PHP
// Item class
class Item {
private string $prop;
public function setProp(string $param1) {
$this->prop = $param1;
}
public function print(): void {
echo "Prop: " . $this->prop . "n";
}
}
// Item factory
class ItemFactory {
public static array $items = [];
public static function getItem(string $type): Item {
if (isset(self::$items[$type])) {
return self::$items[$type];
}
$item = new Item();
self::$items[$type] = $item;
return $item;
}
}
// Demo
// lets generate and print 10,000 objects of different type
$types = ['TYPE_A', 'TYPE_B'];
for ($i = 0; $i < 10000; $i++) {
foreach ($types as $type) {
$item = ItemFactory::getItem($type);
$item->setProp("val_" . rand(0, 1000)); // For demo purpose
$item->print();
}
}
echo "Total number of objects used: " . count(ItemFactory::$items);
The output will be as below-
Prop: val_885
Prop: val_204
Prop: val_648
Prop: val_667
Prop: val_863
Prop: val_610
Prop: val_574
Prop: val_315
Prop: val_150
Prop: val_72
Prop: val_267
Prop: val_550
Prop: val_767
.
.
.
.
.
.
// -- more output here
.
.
.
.
Total number of objects used: 2
You can see the total number of objects used here is 2(two), though we have operated on thousands of items.
Examples
Here are a few examples of Flywieght pattern implementation in PHP.
Example #1: Table Cells
Here we are printing thousands of table cells. We have to create thousands of objects for that, in general implementation.
But if we use flyweight then we can acthive that with very few number of objects.
TableCell Class [Item Class]
- Create file “TableCell.php”.
- Define class “TableCell”.
- Define private property – “width”, “text”.
- “width” is the same for all cells of a column. Set that in the constructor.
- “text” property is different for each cell. So create a setter method for this property, so that we can set it after the object is created.
<?php
// TableCell.php
namespace BigBoxCodeDesignPatternFlyweightTableCell;
class TableCell {
private int $width;
private string $text = '';
public function __construct(int $width) {
$this->width = $width;
}
public function setText(string $text) {
$this->text = $text;
}
public function draw(): void {
echo "Drawing cell : width = " . $this->width . " | text = " . $this->text . "n";
}
}
TableCellFactory Class
- Create file “TableCellFactory.php”.
- Define class “TableCellFactory”.
- Define static property “TableCell”. This is an array that contains a list of “TableCell” objects.
- Define static method “getTableCell”. In the method, if an object exists for a column then return it, else create a new “TableCell” object and return it.
<?php
// TableCellFactory.php
namespace BigBoxCodeDesignPatternFlyweightTableCell;
class TableCellFactory {
public static array $tableCells = [];
public static function getTableCell(int $column, int $width): TableCell {
if (isset(self::$tableCells[$column])) {
return self::$tableCells[$column];
}
$tableCell = new TableCell($width);
self::$tableCells[$column] = $tableCell;
return $tableCell;
}
}
Demo
We have to pass the column and the width to the “getTableCell”, while creating a cell object. The “text” property can be set later.
<?php
// demo.php
require __DIR__ . '/../../vendor/autoload.php';
use BigBoxCodeDesignPatternFlyweightTableCellTableCellFactory;
// For demo there are 5 columns with width 3, 6, 2, 5, 10 of some standard unit
$columnWidths = [3, 6, 2, 5, 10];
// Print 1000 rows
for ($row = 0; $row < 1000; $row++) {
for ($column = 0; $column < count($columnWidths); $column++) {
$tableCell = TableCellFactory::getTableCell($column, $columnWidths[$column]);
$tableCell->setText($row . "-" . $column); // For demo purpose, text can come from any other sources
$tableCell->draw();
}
}
echo "Total number of tree objects: " . count(TableCellFactory::$tableCells);
Output
In the demo code have created about 5k (5 * 1000) objects. But at the end of the output, we can see that only 5 objects were used (one for each column as category).
Output of the code will be as below-
Drawing cell : width = 3 | text = 0-0
Drawing cell : width = 6 | text = 0-1
Drawing cell : width = 2 | text = 0-2
Drawing cell : width = 5 | text = 0-3
Drawing cell : width = 10 | text = 0-4
Drawing cell : width = 3 | text = 1-0
Drawing cell : width = 6 | text = 1-1
Drawing cell : width = 2 | text = 1-2
Drawing cell : width = 5 | text = 1-3
Drawing cell : width = 10 | text = 1-4
Drawing cell : width = 3 | text = 2-0
Drawing cell : width = 6 | text = 2-1
Drawing cell : width = 2 | text = 2-2
Drawing cell : width = 5 | text = 2-3
Drawing cell : width = 10 | text = 2-4
Drawing cell : width = 3 | text = 3-0
Drawing cell : width = 6 | text = 3-1
Drawing cell : width = 2 | text = 3-2
Drawing cell : width = 5 | text = 3-3
Drawing cell : width = 10 | text = 3-4
Drawing cell : width = 3 | text = 4-0
Drawing cell : width = 6 | text = 4-1
Drawing cell : width = 2 | text = 4-2
Drawing cell : width = 5 | text = 4-3
Drawing cell : width = 10 | text = 4-4
Drawing cell : width = 3 | text = 5-0
Drawing cell : width = 6 | text = 5-1
Drawing cell : width = 2 | text = 5-2
Drawing cell : width = 5 | text = 5-3
Drawing cell : width = 10 | text = 5-4
Drawing cell : width = 3 | text = 6-0
Drawing cell : width = 6 | text = 6-1
Drawing cell : width = 2 | text = 6-2
Drawing cell : width = 5 | text = 6-3
Drawing cell : width = 10 | text = 6-4
Drawing cell : width = 3 | text = 7-0
Drawing cell : width = 6 | text = 7-1
Drawing cell : width = 2 | text = 7-2
Drawing cell : width = 5 | text = 7-3
Drawing cell : width = 10 | text = 7-4
Drawing cell : width = 3 | text = 8-0
Drawing cell : width = 6 | text = 8-1
Drawing cell : width = 2 | text = 8-2
Drawing cell : width = 5 | text = 8-3
Drawing cell : width = 10 | text = 8-4
Drawing cell : width = 3 | text = 9-0
Drawing cell : width = 6 | text = 9-1
Drawing cell : width = 2 | text = 9-2
Drawing cell : width = 5 | text = 9-3
Drawing cell : width = 10 | text = 9-4
.
.
.
...// more output lines like this
.
.
.
.
Drawing cell : width = 10 | text = 997-4
Drawing cell : width = 3 | text = 998-0
Drawing cell : width = 6 | text = 998-1
Drawing cell : width = 2 | text = 998-2
Drawing cell : width = 5 | text = 998-3
Drawing cell : width = 10 | text = 998-4
Drawing cell : width = 3 | text = 999-0
Drawing cell : width = 6 | text = 999-1
Drawing cell : width = 2 | text = 999-2
Drawing cell : width = 5 | text = 999-3
Drawing cell : width = 10 | text = 999-4
Total number of tree objects: 5
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Table Cells | GitHub |
Other Code Implementations
Use the following links to check Flyweight pattern implementation in other programming languages.