PHP: Абстрактная Фабрика

Источник: «Abstract Factory Pattern in PHP»
Абстрактная фабрика — шаблон проектирования, предоставляющий интерфейс для создания семейств связанных или независимых объектов без указания конкретных классов.

Абстрактная фабрика позволяет создавать объекты по определённому шаблону без необходимости указывать точный класс создаваемого объекта.

Паттерн Абстрактная фабрика может быть реализован на PHP с использованием интерфейсов и абстрактных классов. Интерфейс или абстрактный класс определяет набор методов, которые должны быть реализованы конкретными фабричными классами отвечающими за создание реальных объектов.

Рассмотрим пример с интерфейсом:

interface CarFactory {
public function createCar(): Car;
public function createTruck(): Truck;
}
interface Car {/*...*/}
class Sedan implements Car {/*...*/}
class SUV implements Car {/*...*/}
interface Truck {/*...*/}
class PickupTruck implements Truck {/*...*/}
class BoxTruck implements Truck {/*...*/}

class FamilyCarFactory implements CarFactory {
public function createCar(): Sedan {
return new Sedan();
}
public function createTruck(): PickupTruck {
return new PickupTruck();
}
}

class LuxuryCarFactory implements CarFactory {
public function createCar(): SUV {
return new SUV();
}
public function createTruck(): BoxTruck {
return new BoxTruck();
}
}

$familyCarFactory = new FamilyCarFactory();
$sedan = $familyCarFactory->createCar();
$pickupTruck = $familyCarFactory->createTruck();

$luxuryCarFactory = new LuxuryCarFactory();
$suv = $luxuryCarFactory->createCar();
$boxTruck = $luxuryCarFactory->createTruck();

В этом примере CarFactory — интерфейс с двумя методами createCar() и createTruck(), которые должны быть реализованы конкретными фабриками. Эти методы создадут объект определённого класса, реализующий интерфейс Car и Track.

Основное преимущество использования паттерна Абстрактная Фабрика — он позволяет разделить задачи между классами создающими объекты и классами использующими их. Интерфейс CarFactory определяет контракт на создание легковых и грузовых автомобилей, в то время как классы конкретных фабрик отвечают за создание реальных объектов.

Используя этот шаблон проектирования, мы можем легко поменять местами конкретные фабричные классы для создания различных типов легковых и грузовых автомобилей без необходимости изменять использующий их код. Например, у нас могут быть разные реализации CarFactory, такие, как FamilyCarFactory и LuxuryCarFactory, где FamilyCarFactory может создавать Sedan и PickupTruck, а LuxuryCarFactorySUV и BoxTruck.

Также мы можем использовать Абстрактную Фабрику для создания различных Фабрик, производящих автомобили использующие различные виды топлива: электричество, бензин, дизель. Таким образом, мы можем создать целое семейство связанных объектов на основе определённой категории с одним фабричным классом.

Рассмотрим пример с использованием абстрактного класса:

abstract class CarFactory {
abstract public function createCar(): Car;
abstract public function createTruck(): Truck;
}

abstract class Car {
abstract public function drive();
}

abstract class Truck {
abstract public function load();
}

class ElectricCar extends Car {
public function drive() {
// code to drive electric car
}
}
class PetrolCar extends Car {
public function drive() {
// code to drive petrol car
}
}
class ElectricTruck extends Truck {
public function load() {
// code to load electric truck
}
}
class PetrolTruck extends Truck {
public function load() {
// code to load petrol truck
}
}

class ElectricCarFactory extends CarFactory {
public function createCar(): ElectricCar {
return new ElectricCar();
}
public function createTruck(): ElectricTruck {
return new ElectricTruck();
}
}
class PetrolCarFactory extends CarFactory {
public function createCar(): PetrolCar {
return new PetrolCar();
}
public function createTruck(): PetrolTruck {
return new PetrolTruck();
}
}

$electricCarFactory = new ElectricCarFactory();
$electricCar = $electricCarFactory->createCar();
$electricCar->drive();

$petrolCarFactory = new PetrolCarFactory();
$petrolCar = $petrolCarFactory->createCar();
$petrolCar->drive();

В этом примере абстрактный класс CarFactory определяет два метода: createCar() и createTruck(), которые должны быть реализованы конкретными фабричными классам. Классы ElectricCarFactory и PetrolCarFactory реализуют эти методы и возвращают новые объекты классов ElectricCar, PetrolCar, ElectricTruck и PetrolTruck.

Вы могли заметить, что абстрактный класс CarFactory определяет контракт и структуру фабрики, в то время как конкретные фабричные классы отвечают за создание реальных объектов Car и Truck.

Использование абстрактных классов также предоставляет возможность совместного использования общих функций между конкретными фабриками. Абстрактный класс может предоставить реализацию по умолчанию для некоторых методов, которые при необходимости могут быть переопределены конкретными классами.

Резюмируя, паттерн Абстрактная Фабрика — мощный инструмент, позволяющий создавать семейства объектов связанных гибким и удобным в сопровождении способом. Используя интерфейсы и абстрактные классы для определения методов создания, можно легко заменить конкретные классы. Использование абстрактного класса позволяет обеспечить реализацию по умолчанию и совместно использовать общие функции между конкретными фабриками.

Дополнительные материалы

Предыдущая Статья

JavaScript: Как использовать Коллекции — Map и Set

Следующая Статья

Laravel 10: Фасад Process