What is factory pattern in php

Шаблоны проектирования в PHP : Фабрика

Фабрика (Factory) — один из наиболее часто применяемых шаблонов проектирования в программировании, обычно его используют в случае, когда во время исполнения программы необходимо выбрать один из взаимозаменяемых классов.

В целом, это удобный способ создания объектов. Фабрика (Factory) способна создавать объекты различных классов, при этом ей совсем необязательно знать тип объекта который она создает.

Шаблон проектирования Фабрика направлен на решение проблемы сильно связанных классов в больших приложениях. Она позволяет создавать объекты без вызова new.

Существует несколько способов реализации этого шаблона:

  • Простая фабрика (Simple Factory)
  • Абстрактная фабрика (Abstract Factory)
  • Фабричный метод (Factory Method)

В этой статье мы рассмотрим последний метод, так как он более близок к официальному определению шаблона и чаще находит применение в практическом программировании. Так же, хотелось бы отметить, что шаблон проектирования Простая фабрика, большинство разработчиков не считают шаблоном вовсе. Лично я считаю, что этот способ реализации вполне достоин называться шаблоном, хотя он и очень прост в реализации. Но этот спор — не цель статьи. Из названия понятно, что способ Фабричный метод использует метод класса для создания объектов.

Когда же использовать шаблон фабрика?

Теперь мы знаем, что из себя представляет такой шаблон проектирования, как фабрика, но когда же целесообразно его использовать? Вот несколько примеров:

  1. Класс не может заранее знать какого типа объект ему предстоит создать
  2. Мы хотим скрыть логику создания сложного объекта
  3. Хотим уменьшить сильные связи между классами приложения

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

А где же код?

Представьте, что мы работаем первый день на проектом Фабрика изделий Икея и нам предстоит поддерживать и обновлять существующий код. Как вы можете себе представить у Икеи есть бесконечное множество разных изделий и типов изделий. Только представьте себе, если бы каждое изделие соответствовало отдельному классу. Тогда бы наш код выглядел примерно так:

 abstract class Product  private $sku; private $name; protected $type = null; public function __construct($sku, $name)  $this->sku = $sku; $this->name = $name; > public function getSku()  return $this->sku; > public function getName()  return $this->name; > public function getType()  return $this->type; > > class ProductChair extends Product  protected $type = 'chair'; > class ProductTable extends Product  protected $type = 'table'; > class ProductBookcase extends Product  protected $type = 'bookcase'; > class ProductSofa extends Product  protected $type = 'sofa'; >

В примере выше мы видим абстрактный класс Product, реализацию конструктора объекта этого класса, и набор геттеров и сеттеров. Для каждого продукта у нас есть свой класс, который наследуются от класса Product.

Вы наверняка заметили из кода выше, что необходимо будет сделать множество вызовов для инициализации каждого объекта, например:

 $product = new ProductChair('0001','INGOLF Chair'); ... $product = new ProductTable('0002','STOCKHOLN Table'); ...

Проблема становится более явной если, например, у нас есть контроллер по адресу http://factory.ikea.com/product/create/ , который отвечает за создание объектов в зависимости от параметра product_type , проверку и добавление информации о объекте и его сохранение.

На время опустим логику проверки и добавления информации, для нас сейчас важнее то, как создаётся объект без использования шаблона.

 class ProductController  public function create($productType)  // Логика валидации продукта // Здесь нам нужно создать нужный продукт switch($productType)  case 'chair': $product = new ProductChair($post['sku'], $post['name']); break; case 'table': $product = new ProductTable($post['sku'], $post['name']); break; case 'sofa': $product = new ProductSofa($post['sku'], $post['name']); break; case 'bookcase': $product = new ProductBookcase($post['sku'], $post['name']); break; > // Do something with the post data and save the product // . return $product->getType(); > >

Какова же основная проблема? Так как заранее мы не знаем какой тип объекта нам понадобится, нам приходится использовать switch для инициализации.

Вы наверняка спросите, что же в этом плохого. Цель ведь достигнута. Не забывайте, что это в нашем приложении сотни разных классов, то есть нам бы пришлось использовать сто выражений case .

Предыдущий пример к тому же довольно тяжело поддерживать и расширять. Что если бы нам пришлось добавить новый параметр в метод __construct? Как следствие нам пришлось бы обновить каждый вызов этого метода.

Давайте посмотрим как использование шаблона Фабричный метод может упростить нам жизнь. Для начала создадим новый класс ProductFactory.

 class ProductFactory  public static function build($productType, $sku, $name)  $product = "Product" . ucfirst($productType); if (class_exists($product))  return new $product($sku, $name); > else  throw new \Exception("Неверный тип продукта"); > > >

Теперь используем этот класс в нашем контроллере:

 class ProductController  public function create($productType)  // Валидация продукта // Здесь создаём продукт с помощью Фабричного метода $product = ProductFactory::build($productType, $post['sku'], $post['name']); // Что-то делаем с продуктом и сохраняем // . return $product->getType(); > >

Только представьте, только что мы заменили сотни строк кода на одну $product = ProductFactory::build($productType, $post[‘sku’], $post[‘name’]);. Теперь если бы мы столкнулись с проблемой изменения логики инициализации в конструкторе, нам бы пришлось исправить только код в этом классе.

Выводы

В статье мы рассмотрели преимущества использования такого шаблона проектирования как Фабричный метод. Он позволяет не только упростить код, но и сделать его более простым для дальнейшей поддержки. Несмотря на то, что примеры мы использовали довольно простые, мы смогли показать суть шаблона.

Исходный код шаблона доступен на github. Оставляйте свои замечания и исправления в комментариях.

Читайте также

Шаблоны проектирования в PHP : Команда Задумывались ли вы, что сейчас люди используют больше 4 миллиардов мобильных устройств? В Австралии население составляет примерно 11 миллионов человек,…

Шаблоны проектирования в PHP : Адаптер Шаблон проектирования — Адаптер (Adapter) Название шаблона говорит само за себя. Он помогает адаптировать ваш код к новым требованиям, не…

Шаблоны проектирования в PHP : Цепочка обязанностей Назначение паттерна? Паттерн Chain of Responsibility (Цепочка обязянностей) позволяет избежать жесткой зависимости отправителя запроса от его получателя (т.е. обеспечивается слабая связанность компонентов…

Источник

What is the PHP Factory Pattern?

The factory pattern is a creational pattern that provides an optimal way to create objects. In the factory mode, we do not expose the creation logic to the client when creating an object, but use a common interface to point to the newly created object.

Advantages of the factory pattern

  1. The factory pattern can help us achieve loose coupling, which separates the client code from the code that actually creates objects;
  2. The factory pattern can help us encapsulate changes. The client code does not need to know the actual created object, but only needs to know the factory;
  3. The factory pattern can help us realize the principle of single responsibility. A class is responsible for only one responsibility, and the factory class is responsible for creating objects.

Implementation of the factory pattern

1. Simple factory pattern

The simple factory pattern is a factory pattern that encapsulates the creation logic in a class. In the simple factory mode, we use a factory class to create all objects, and return different object instances according to the parameters passed in.

 // implement the interface class Benz implements Car < public function run() < echo 'Benz is running. '; >> // implement the interface class Bmw implements Car < public function run() < echo 'Bmw is running. '; >> // factory class class CarFactory < public static function createCar($type) < switch ($type) < case 'Benz': return new Benz(); case 'Bmw': return new Bmw(); default: throw new Exception('Undefined car type.'); >> > // use $car1 = CarFactory::createCar('Benz'); $car1->run(); // output: Benz is running. $car2 = CarFactory::createCar('Bmw'); $car2->run(); // output: Bmw is running.

2. Factory method pattern

The factory method pattern is a factory pattern that delegates the creation of objects to a specific factory class. In the factory method pattern, we define an interface for creating objects, and subclasses decide which class to instantiate.

 // implement the interface class Benz implements Car < public function run() < echo 'Benz is running. '; >> // implement the interface class Bmw implements Car < public function run() < echo 'Bmw is running. '; >> // Define the factory interface interface CarFactory < public function createCar(); >// Implement the factory interface class BenzFactory implements CarFactory < public function createCar() < return new Benz(); >> // Implement the factory interface class BmwFactory implements CarFactory < public function createCar() < return new Bmw(); >> // use $benzFactory = new BenzFactory(); $car1 = $benzFactory->createCar(); $car1->run(); // output: Benz is running. $bmwFactory = new BmwFactory(); $car2 = $bmwFactory->createCar(); $car2->run(); // output: Bmw is running.

3. Abstract factory pattern

The abstract factory pattern is a factory pattern that delegates the creation of multiple objects to a specific factory class. In the abstract factory pattern, we define an abstract factory interface, which is implemented by a specific factory class to create multiple related objects.

 // implement the interface class Benz implements Car < public function run() < echo 'Benz is running. '; >> // implement the interface class Bmw implements Car < public function run() < echo 'Bmw is running. '; >> // Define the abstract factory interface interface CarFactory < public function createBenz(); public function createBmw(); >// Implement the abstract factory interface class Factory implements CarFactory < public function createBenz() < return new Benz(); >public function createBmw() < return new Bmw(); >> // use $factory = new Factory(); $car1 = $factory->createBenz(); $car1->run(); // output: Benz is running. $car2 = $factory->createBmw(); $car2->run(); // output: Bmw is running.

Summarize

Posted by tom100 on Wed, 22 Mar 2023 15:27:02 -0700

Источник

Читайте также:  Решение задач питон тьютор ответы
Оцените статью