Factory Method (Фабричный метод)
Паттерн проектирования Factory Method
Описание Factory Method
Фабричный метод (англ. Factory Method также известен как Виртуальный конструктор (англ. Virtual Constructor)) — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс создавать. Иными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне.
Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать. Фабричный метод позволяет классу делегировать создание подклассов. Используется, когда:
- классу заранее неизвестно, объекты каких подклассов ему нужно создавать.
- класс спроектирован так, чтобы объекты, которые он создаёт, специфицировались подклассами.
- класс делегирует свои обязанности одному из нескольких вспомогательных подклассов, и планируется локализовать знание о том, какой класс принимает эти обязанности на себя
Структура
- Product — продукт
- определяет интерфейс объектов, создаваемых абстрактным методом;
- ConcreteProduct — конкретный продукт
- реализует интерфейс Product;
- Creator — создатель
- объявляет фабричный метод, который возвращает объект типа Product. Может также содержать реализацию этого метода «по умолчанию»;
- может вызывать фабричный метод для создания объекта типа Product;
- ConcreteCreator — конкретный создатель
- переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.
Примеры реализации
// Factory Method Pattern in JavaScript
class Product {
operation() {
throw new Error('Method must be implemented');
}
}
class ConcreteProductA extends Product {
operation() {
return 'ConcreteProductA operation';
}
}
class ConcreteProductB extends Product {
operation() {
return 'ConcreteProductB operation';
}
}
class Creator {
factoryMethod() {
throw new Error('Method must be implemented');
}
someOperation() {
const product = this.factoryMethod();
return product.operation();
}
}
class ConcreteCreatorA extends Creator {
factoryMethod() {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
factoryMethod() {
return new ConcreteProductB();
}
}
// Usage
const creatorA = new ConcreteCreatorA();
const creatorB = new ConcreteCreatorB();
console.log(creatorA.someOperation());
console.log(creatorB.someOperation());
// Factory Method Pattern in C++
#include <iostream>
#include <memory>
class Product {
public:
virtual ~Product() = default;
virtual std::string operation() = 0;
};
class ConcreteProductA : public Product {
public:
std::string operation() override {
return "ConcreteProductA operation";
}
};
class ConcreteProductB : public Product {
public:
std::string operation() override {
return "ConcreteProductB operation";
}
};
class Creator {
public:
virtual ~Creator() = default;
virtual std::unique_ptr<Product> factoryMethod() = 0;
std::string someOperation() {
auto product = factoryMethod();
return product->operation();
}
};
class ConcreteCreatorA : public Creator {
public:
std::unique_ptr<Product> factoryMethod() override {
return std::make_unique<ConcreteProductA>();
}
};
class ConcreteCreatorB : public Creator {
public:
std::unique_ptr<Product> factoryMethod() override {
return std::make_unique<ConcreteProductB>();
}
};
// Factory Method Pattern in Go
package main
import "fmt"
type Product interface {
Operation() string
}
type ConcreteProductA struct{}
func (p *ConcreteProductA) Operation() string {
return "ConcreteProductA operation"
}
type ConcreteProductB struct{}
func (p *ConcreteProductB) Operation() string {
return "ConcreteProductB operation"
}
type Creator interface {
FactoryMethod() Product
SomeOperation() string
}
type ConcreteCreatorA struct{}
func (c *ConcreteCreatorA) FactoryMethod() Product {
return &ConcreteProductA{}
}
func (c *ConcreteCreatorA) SomeOperation() string {
product := c.FactoryMethod()
return product.Operation()
}
type ConcreteCreatorB struct{}
func (c *ConcreteCreatorB) FactoryMethod() Product {
return &ConcreteProductB{}
}
func (c *ConcreteCreatorB) SomeOperation() string {
product := c.FactoryMethod()
return product.Operation()
}
// Usage
func main() {
creatorA := &ConcreteCreatorA{}
creatorB := &ConcreteCreatorB{}
fmt.Println(creatorA.SomeOperation())
fmt.Println(creatorB.SomeOperation())
}
# Factory Method Pattern in Python
from abc import ABC, abstractmethod
class Product(ABC):
@abstractmethod
def operation(self):
pass
class ConcreteProductA(Product):
def operation(self):
return "ConcreteProductA operation"
class ConcreteProductB(Product):
def operation(self):
return "ConcreteProductB operation"
class Creator(ABC):
@abstractmethod
def factory_method(self):
pass
def some_operation(self):
product = self.factory_method()
return product.operation()
class ConcreteCreatorA(Creator):
def factory_method(self):
return ConcreteProductA()
class ConcreteCreatorB(Creator):
def factory_method(self):
return ConcreteProductB()
# Usage
if __name__ == "__main__":
creator_a = ConcreteCreatorA()
creator_b = ConcreteCreatorB()
print(creator_a.some_operation())
print(creator_b.some_operation())
<?php
// Factory Method Pattern in PHP
abstract class Product {
abstract public function operation(): string;
}
class ConcreteProductA extends Product {
public function operation(): string {
return "ConcreteProductA operation";
}
}
class ConcreteProductB extends Product {
public function operation(): string {
return "ConcreteProductB operation";
}
}
abstract class Creator {
abstract public function factoryMethod(): Product;
public function someOperation(): string {
$product = $this->factoryMethod();
return $product->operation();
}
}
class ConcreteCreatorA extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductB();
}
}
// Usage
$creatorA = new ConcreteCreatorA();
$creatorB = new ConcreteCreatorB();
echo $creatorA->someOperation() . "\n";
echo $creatorB->someOperation() . "\n";
?>