Действующий пример использования в приложении шаблона проектирования Абстрактная фабрика.
Сегодня рассмотрим, как можно применить шаблон проектирования Абстрактная фабрика в приложении. В предыдущей записи с описанием шаблона Абстрактная фабрика, упоминалось, что зачастую приложению могут понадобиться элементы пользовательского интерфейса разного дизайна. Вот и будем развивать эту тему. В описании кода я опущу некоторые детали, чтобы выделить сам шаблон, но полный текст примера для скачивания будет приведен в конце.
Пример использования шаблона Абстрактная фабрика
Предположим, что мы предоставили пользователю возможность выбрать вид элементов для разных тем нашего приложения. Не только выбрать, но и увидеть, как они будут выглядеть.
Замечу, сервер не догадывается, какую тему захочет выбрать пользователь. Набор элементов один и тот же, различие только в деталях отрисовки — просится типовая обработка запроса. Вот здесь то и будет удобен паттерн Абстрактная фабрика.
Вначале создаем иерархию фабрик.
<?php
abstract class Factory
{
abstract public function createLabel();
abstract public function createButton();
}
class FactoryLight extends Factory
{
public function createLabel()
{
return new LabelLight();
}
public function createButton()
{
return new ButtonLight();
}
}
class FactoryDark extends Factory
{
public function createLabel()
{
return new LabelDark();
}
public function createButton()
{
return new ButtonDark();
}
}
Теперь создаем иерархию продуктов.
<?php
abstract class Label
{
protected $caption = 'Label';
public function getCaption()
{
return $this->caption;
}
public function setCaption($str)
{
$this->caption = $str;
}
abstract public function render();
}
class LabelLight extends Label
{
public function render()
{
$str = '<label>';
$str .= $this->caption;
$str .= '</label>';
return $str;
}
}
class LabelDark extends Label
{
public function render()
{
$str = '<label>';
$str .= $this->caption;
$str .= '</label>';
return $str;
}
}
abstract class Button
{
protected $value = 'Button';
public function getValue()
{
return $this->value;
}
public function setValue($str)
{
$this->value = $str;
}
abstract function render();
}
class ButtonLight extends Button
{
function render()
{
$str = '<input type="button" ';
$str .= "value=\"$this->value\">";
return $str;
}
}
class ButtonDark extends Button
{
function render()
{
$str = '<input type="button" ';
$str .= "value=\"$this->value\">";
return $str;
}
}
Классы шаблона созданы, теперь пишем обработчик запроса.
<?php
require 'Elements.php';
require 'AbstFactory.php';
$theme = $_GET["theme"];
$factory = getFactory($theme);
$response = getResponse($factory, $theme);
echo $response;
function getFactory($theme)
{
switch ($theme) {
case 'light' :
$factoryElem = new FactoryLight();
break;
case 'dark' :
$factoryElem = new FactoryDark();
break;
}
return $factoryElem;
}
function getResponse($factory, $theme)
{
$themeName = ucfirst($theme);
$label = $factory->createLabel();
$label->setCaption('Текст метки');
$button = $factory->createButton();
$button->setValue('Отправить');
$response = include 'table.php';
return $response;
}
Выводы
Подведем итоги. Да, над созданием классов фабрик и семейств продуктов пришлось потрудиться, зато в обработчике запроса код простой и не зависит от типа создаваемого объекта. Более того, если понадобится еще одна тема, доработка обработчика запроса будет минимальной, а значит и вероятность внесения ошибок в приложение в результате правок также будет минимальной.
Исходные коды примера вы можете скачать по этой ссылке. Для его работы нужны лишь Web сервер и PHP.
Перейти к списку шаблонов проектирования.