<?php
namespace RefactoringGuru\FactoryMethod\Conceptual;
/**
* Паттерн Фабричный Метод
*
* Назначение: Определяет общий интерфейс для создания объектов в суперклассе,
* позволяя подклассам изменять тип создаваемых объектов.
*/
/**
* Класс Создатель объявляет фабричный метод, который должен возвращать объект
* класса Продукт. Подклассы Создателя обычно предоставляют реализацию этого
* метода.
*/
abstract class Creator
{
/**
* Обратите внимание, что Создатель может также обеспечить реализацию
* фабричного метода по умолчанию.
*/
abstract public function factoryMethod(): Product;
/**
* Также заметьте, что, несмотря на название, основная обязанность Создателя
* не заключается в создании продуктов. Обычно он содержит некоторую базовую
* бизнес-логику, которая основана на объектах Продуктов, возвращаемых
* фабричным методом. Подклассы могут косвенно изменять эту бизнес-логику,
* переопределяя фабричный метод и возвращая из него другой тип продукта.
*/
public function someOperation(): string
{
// Вызываем фабричный метод, чтобы получить объект-продукт.
$product = $this->factoryMethod();
// Далее, работаем с этим продуктом.
$result = "Creator: creator's code has just worked with " . $product->operation();
return $result;
}
}
/**
* Конкретные Создатели переопределяют фабричный метод для того, чтобы изменить
* тип результирующего продукта.
*/
class ConcreteCreator1 extends Creator
{
/**
* Обратите внимание, что сигнатура метода по-прежнему использует тип
* абстрактного продукта, хотя фактически из метода возвращается конкретный
* продукт. Таким образом, Создатель может оставаться независимым от
* конкретных классов продуктов.
*/
public function factoryMethod(): Product
{
return new ConcreteProduct1();
}
}
class ConcreteCreator2 extends Creator
{
public function factoryMethod(): Product
{
return new ConcreteProduct2();
}
}
/**
* Интерфейс Продукта объявляет операции, которые должны выполнять все
* конкретные продукты.
*/
interface Product
{
public function operation(): string;
}
/**
* Конкретные Продукты предоставляют различные реализации интерфейса Продукта.
*/
class ConcreteProduct1 implements Product
{
public function operation(): string
{
return "{Result of the ConcreteProduct1}";
}
}
class ConcreteProduct2 implements Product
{
public function operation(): string
{
return "{Result of the ConcreteProduct2}";
}
}
/**
* Клиентский код работает с экземпляром конкретного создателя, хотя и через его
* базовый интерфейс. Пока клиент продолжает работать с создателем через базовый
* интерфейс, вы можете передать ему любой подкласс создателя.
*/
function clientCode(Creator $creator)
{
// ...
echo "Client: I'm not aware of the creator's class, but it still works.\n"
. $creator->someOperation();
// ...
}
/**
* Приложение выбирает тип создателя в зависимости от конфигурации или среды.
*/
echo "App: Launched with the ConcreteCreator1.\n";
clientCode(new ConcreteCreator1());
echo "\n\n";
echo "App: Launched with the ConcreteCreator2.\n";
clientCode(new ConcreteCreator2());
Output for git.master, git.master_jit, rfc.property-hooks
App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: creator's code has just worked with {Result of the ConcreteProduct1}
App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: creator's code has just worked with {Result of the ConcreteProduct2}
This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.