Фабричный метод - 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
- 4986 reads