Шаблон Factory Method (Фабричный метод) на PHP
03-07-2019Reading time ~ 2 min.PHP/ООП 8970
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();
По сути это одно и тоже, только писать кода придется больше. :-)