07/05/2018 - SYMFONY
Flyweight design pattern is used to minimise memory usage by sharing as much memory as possible with same objects. It is like caching mechanism but no cache is involved. In this example we are going to render templates. If a template was rendered before we will get the previous version. The important point here is it wouldn't work with dynamic dataset. You have to make sure that the data returned is exactly what you would need.
declare(strict_types=1);
namespace App\Controller;
use App\Flyweight\Factory\TemplateRenderFactory;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Routing\Annotation\Route;
class FlyweightController
{
private $templateRenderFactory;
public function __construct(TemplateRenderFactory $templateRenderFactory)
{
$this->templateRenderFactory = $templateRenderFactory;
}
public function index()
{
$template1 = $this->templateRenderFactory->create('flyweight/home.txt.twig');
$template2 = $this->templateRenderFactory->create('flyweight/home.txt.twig');
$template3 = $this->templateRenderFactory->create('flyweight/contact.txt.twig');
$template4 = $this->templateRenderFactory->create('flyweight/contact.txt.twig');
$content1 = $template1->render();
$content2 = $template2->render();
$content3 = $template3->render();
$content4 = $template4->render();
print_r(
[
'template1_obj_id' => md5(spl_object_hash($template1)),
'content1' => $content1,
'template2_obj_id' => md5(spl_object_hash($template2)),
'content2' => $content2,
'template3_obj_id' => md5(spl_object_hash($template3)),
'content3' => $content3,
'template4_obj_id' => md5(spl_object_hash($template4)),
'content4' => $content4,
'count' => $this->templateRenderFactory->count(),
]
);
}
}
declare(strict_types=1);
namespace App\Flyweight\Factory;
use App\Flyweight\TemplateRenderFlyweight;
use App\Flyweight\RenderFlyweightInterface;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class TemplateRenderFactory
{
private $templating;
private $pool = [];
public function __construct(EngineInterface $templating)
{
$this->templating = $templating;
}
public function create(string $template): RenderFlyweightInterface
{
if (!isset($this->pool[$template])) {
$this->pool[$template] = new TemplateRenderFlyweight($this->templating, $template);
}
return $this->pool[$template];
}
public function count(): int
{
return count($this->pool);
}
}
declare(strict_types=1);
namespace App\Flyweight;
interface RenderFlyweightInterface
{
public function render(): string;
}
declare(strict_types=1);
namespace App\Flyweight;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class TemplateRenderFlyweight implements RenderFlyweightInterface
{
private $templating;
private $template;
public function __construct(EngineInterface $templating, string $template)
{
$this->templating = $templating;
$this->template = $template;
}
public function render(): string
{
return $this->templating->render($this->template);
}
}
Content of the "home" page.
Content of the "contact" page.
We requested two home and two contact pages. As you can see below, there has been only one copy of each page request instead of two.
Array
(
[template1_obj_id] => 9ccbdd93639d71e7787c557c54e5e3dc
[content1] => Content of the "home" page.
[template2_obj_id] => 9ccbdd93639d71e7787c557c54e5e3dc
[content2] => Content of the "home" page.
[template3_obj_id] => 1ac487dee09b2da4db43a0da55bccecb
[content3] => Content of the "contact" page.
[template4_obj_id] => 1ac487dee09b2da4db43a0da55bccecb
[content4] => Content of the "contact" page.
[count] => 2
)