Введение
Довольно часто в программе мы имеем несколько объектов (не экземпляры классов), и у всех этих объектов есть одинаковые задачи, но реализуются они по-разному. Как сделать так, чтобы программа была более читабельной, легко расширялась и не имела дублирования кода? Нам на помощь приходит паттерн Factory, который поможет нам спроектировать нашу программу, сделать ее более гибкой и «правильной».
Задача
У нас есть завод, на котором производят автомобили (Заметили? Очень часто в примерах о шаблонах проектирования используются автомобили). Завод может выпускать 3 типа машин (Fast Car, Big Car, Cheap Car). Для создания каждого типа автомобиля завод имеет свой конвейер. У каждого конвейера есть 3 функции (сборка двигателя, приделывание колес, тестирование на практике).
Реализация
Так как завод может приобрести еще один конвейер для создания нового типа авто, то нам нужно позаботиться о гибкости нашей системы. Говоря языком программирования, конвейеры должны реализовывать один интерфейс.
Интерфейс
interface Сonveyer
{
public function buildEngine();
public function attachWheels();
public function testing();
}
Наши конвейеры должны реализовать этот несложный интерфейс. Набросаем классы для каждого из них.
Fast Car
class Fast_Car implements Сonveyer
{
public function buildEngine
(
// делаем быстрый двигатель
);
public function attachWheels
(
// делаем быстрые колеса
);
public function testing
(
// тестируем на быстрой трассе
);
}
Big Car
class Big_Car implements Сonveyer
{
public function buildEngine
(
// делаем большой двигатель
);
public function attachWheels
(
// делаем большие колеса
);
public function testing
(
// тестируем на массивной трассе
);
}
Cheap Car
class Cheap_Car implements Сonveyer
{
public function buildEngine
(
// делаем дешевый двигатель
);
public function attachWheels
(
// делаем дешевые колеса
);
public function testing
(
// тестируем за забором
);
}
А также у нас на заводе имеется аппарат, который выбирает, какую машину сейчас делать. Этот аппарат и будет нашей абстрактной фабрикой:
class Car_Factory
{
public static function factory($car)
{
$class_name = $car; // Допустим, название класса и машины у нас совпадают
require ($car . '.php'); // Допустим, название класса и файла тоже совпадают
$object = new $class_name;
return $object;
}
}
И работа нашего аппарата по выбору производимой машины:
$obj = Car_Factory::factory('Big_Car');
$obj -> buildEngine();
$obj -> attachWheels();
$obj -> testing();
Заключение
Теперь можем увольняться с завода. Придет новый инженер, посмотрит на наш интерфейс, поймет, какой функционал нужно реализовать, напишет класс, и всё будет работать.
Я делал упор не на конкретное программирование, а на понимание сути этого шаблона проектирования.