Фабричный метод - PHP
Primary tabs
Рассмотрим простой пример Фабричного метода - с минимальным набором сущностей:
/* Абстрактный "создатель" -
в данном примере выполнен в виде интерфейса -
но можно использовать и класс - в том числе - абстрактный класс */
interface CarFactory {
// вот этот метод как раз и называют фабричным
public function makeCar(); // фабр. метод
}
/*Абстрактный "продукт"*/
interface Car {
// здесь может быть какой угодно набор методов
public function getType();
}
/* Далее будут приведены конкретные реализации
абстракций создателя и продукта */
/* конкретный "создатель" - фабрика кузовов типа "сидан" */
class SedanFactory implements CarFactory {
/* следующий метод - это как раз
конкретная реалзизация фабричного метода makeCar()*/
public function makeCar() { // создаём кузов
return new Sedan();
}
}
/* конкретный продукт - напр. кузов машины типа "сидан"*/
class Sedan implements Car {
public function getType() { // например возврат конкретного типа
return 'Sedan';
}
}
/* Далее - клиенский код -
то есть пример эксплуатации созданных выше двух иерархий классов*/
$factory = new SedanFactory(); // создаём фабрику
$car = $factory->makeCar(); // вызываем фабричный метод и получаем машину (кузов)
print $car->getType(); // начинаем работать с полученным объектомЕщё раз повторюсь - что приведённый выше пример является минимальным - он строго говоря даже не демонстрирует удобство использования паттерна "Фабричный метод"-
Ведь на самом деле вся фишка в клиенском коде. - дело в том, что оказывается удобным создать для клиента универсальную функцию для работы с различными создателями (фабриками) -и параметризовать её уже объектом-фабрикой (создателем)/
Например так:
<?
/*пример клиенского кода для фабричного метода
который НЕ ЗАВИСИТ от того какую именно конкретную фабрику
(конкретного создателя) передадут ему*/
class Project // некий охватывающий контекст класс
{
public $factory = "";
/*получаем конкретную фабрику в конструкторе -
например от меню когда пользователь выбрал нужный тип машины*/
__construct($factory){ // получаем
$this->factory = $factory; // сохраняем эту фабрику
}
function GetProduct()
{
// используем фабрику полунную при создании контекста
$car = $this->factory->makeCar();
return $car;
}
/* метод ниже будем рассматривать как клиентский код*/
function GetCarName() // "клиент"
{
$car = $this->GetProduct($this->factory);
print $car->getType(); // выводим тип
}
/*----какие-то ещё методы-----*/
}
Теперь (когда мы определили класс Project) "непосредственно клиенский" код может выглядеть так:
/* Далее - клиенский код -
то есть пример эксплуатации созданных выше двух иерархий классов*/
if ($menuitem == 'sedan') // какое-то условие (например пользователь выбрал пункт меню)
{
$factory = new SedanFactory(); // создаём фабрику
}
/*
выше сделан выбор, а далее
идёт абсолютно "гибкий" код клиента
*/
$project = new Project($factory); // этот класс не знает заранее "с кем" будет работать -
// но при этом мы ("клиент") также не знаем какую именно машину получим в $car
$car = $project->GetProduct(); // вызываем фабричный метод и получаем машину (кузов)
print $car->getType(); // начинаем работать с полученным объектом
Последний приведённый фрагмент кода вполне можно считать демонстрацией использования паттерна фабричный метод, ведь данный пример:
- использует для порождения конкретной машины (продукта) конкретную фабрику (класс-создатель) - кстати именно это и есть формальный признак использования шаблона фабричный метод
- приведённый фрагмент во второй своей части "гибок" - то есть при добавлении новых классов вторую часть кода редактировать вообще не придётся - таким образом данный паттерн облегчает жизнь разработчика
- Log in to post comments
- 5259 reads