Сайт вебмастера

Шаблон Factory Method (Фабричный метод) на PHP

03-07-2019Время чтения ~ 2 мин.PHP/ООП 8791

Factory Method (Фабричный метод) немного похож на Абстрактную фабрику. Он также позволяет спрятать конкретную реализацию и предоставить несколько типовых методов для использования.

Но, о отличие от абстрактной фабрики, фабричный метод даёт возможность задать какой именно класс «реализации» использовать в конкретной фабрике.

Исходный код шаблона вы найдете на гитхабе.

Существует несколько вариантов реализации Factory Method, я остановился на статическом методе. На самом деле это не обязательно, можно использовать и обычные методы, хотя это увеличит размер кода.

Итак. У фабрик должен быть единый интерфейс. Для этого мы используем абстрактный класс CommonAbstract, который сам может содержать обязательные методы, а также статичный метод initial(), через который собственно и происходит инстанцирование нужного «подкласса» (Class1 и Class2). Абстрактный класс, в отличие от интерфейса, позволяет создать общую функциональность, что немного упрощает код в расширяющих его классах.

Абстрактный метод run() говорит о том, что этот метод должен быть реализован во всех фабриках.

При создании фабрики, нужно сразу указывать какой именно класс реализации будет использован.

$a = CommonAbstract::initial('Class1');
$a->run(); // Class1 run
 
$b = CommonAbstract::initial('Class2');
$b->run(); // Class2 run

Какой именно вариант, зависит от задач. Например так:

$type_file = 'zip'; // rar, arj
 
if ($type_file == 'zip') {
    $f = CommonAbstract::initial('ZipClass');
} elseif ($type_file == 'rar') {
    $f = CommonAbstract::initial('RarClass');
} else {
    $f = CommonAbstract::initial('OtherClass');
}
 
$f->pack();

В абстрактной фабрике все «подклассы» были жестко заданы в каждой фабрике. Здесь же мы можем не меняя кода базового класса, просто добавить ещё один класс и подключить его через CommonAbstract::initial.

Существует ещё одна модификация Фабричного метода, которая отличается от этой способом инстанцирования. Здесь используется статичный метод, но можно сразу передать в CommonAbstract готовый класс. Тогда в методе initial инстанцирование уже не нужно.

$type_file = 'zip'; // rar, arj
 
if ($type_file == 'zip') {
	$zip = new ZipClass();
    $f = CommonAbstract::initial($zip);
} elseif ($type_file == 'rar') {
    $f = CommonAbstract::initial(new RarClass()); // или так
} else {
    $other= new OtherClass();
    $f = CommonAbstract::initial($other);
}
 
$f->pack();

По сути это одно и тоже, только писать кода придется больше. :-)

Похожие записи