Design Pattern: Flyweight Pattern in PHP

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 BigBoxCode\DesignPattern\Flyweight\TableCell;


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 BigBoxCode\DesignPattern\Flyweight\TableCell;

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 BigBoxCode\DesignPattern\Flyweight\TableCell\TableCellFactory;


// 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:

Other Code Implementations

Use the following links to check Flyweight pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.