Паттерн Factory Method определяет интерфейс для создания объектов, но позволяет подклассам решать, какой класс инстанцировать. Он делегирует создание объектов дочерним классам, обеспечивая гибкость и расширяемость системы.
Когда применять Factory Method
- Когда заранее неизвестно, какие конкретные объекты нужно создавать.
- Чтобы избавиться от жёстких зависимостей между классами.
- Чтобы добавить новые типы продуктов без изменения существующего кода.
PlantUML-диаграмма
public interface ITransport
{
void Deliver();
}
public class Truck : ITransport
{
public void Deliver()
{
Console.WriteLine("Доставка грузов по суше на грузовике.");
}
}
public class Ship : ITransport
{
public void Deliver()
{
Console.WriteLine("Доставка товаров по морю на корабле.");
}
}
public abstract class Logistics
{
public abstract ITransport CreateTransport();
public void PlanDelivery()
{
var transport = CreateTransport();
transport.Deliver();
}
}
public class RoadLogistics : Logistics
{
public override ITransport CreateTransport() => new Truck();
}
public class SeaLogistics : Logistics
{
public override ITransport CreateTransport() => new Ship();
}
// Использование
class Program
{
static void Main()
{
Logistics logistics = new RoadLogistics();
logistics.PlanDelivery();
logistics = new SeaLogistics();
logistics.PlanDelivery();
}
}
type Transport interface {
Deliver()
}
type Truck struct{}
func (Truck) Deliver() { fmt.Println("Доставка грузов по суше на грузовике.") }
type Ship struct{}
func (Ship) Deliver() { fmt.Println("Доставка товаров по морю на корабле.") }
// Абстрактных классов в Go нет: общую часть выносим в функцию,
// а «фабричный метод» передаём обычной функцией-конструктором.
type Logistics func() Transport
func (create Logistics) PlanDelivery() {
create().Deliver()
}
func RoadLogistics() Transport { return Truck{} }
func SeaLogistics() Transport { return Ship{} }
func main() {
var logistics Logistics = RoadLogistics
logistics.PlanDelivery()
logistics = SeaLogistics
logistics.PlanDelivery()
}
from abc import ABC, abstractmethod
class Transport(ABC):
@abstractmethod
def deliver(self) -> None: ...
class Truck(Transport):
def deliver(self) -> None:
print("Доставка грузов по суше на грузовике.")
class Ship(Transport):
def deliver(self) -> None:
print("Доставка товаров по морю на корабле.")
class Logistics(ABC):
@abstractmethod
def create_transport(self) -> Transport: ...
def plan_delivery(self) -> None:
self.create_transport().deliver()
class RoadLogistics(Logistics):
def create_transport(self) -> Transport:
return Truck()
class SeaLogistics(Logistics):
def create_transport(self) -> Transport:
return Ship()
logistics: Logistics = RoadLogistics()
logistics.plan_delivery()
logistics = SeaLogistics()
logistics.plan_delivery()
interface Transport {
deliver(): void;
}
class Truck implements Transport {
deliver(): void {
console.log("Доставка грузов по суше на грузовике.");
}
}
class Ship implements Transport {
deliver(): void {
console.log("Доставка товаров по морю на корабле.");
}
}
abstract class Logistics {
abstract createTransport(): Transport;
planDelivery(): void {
this.createTransport().deliver();
}
}
class RoadLogistics extends Logistics {
createTransport(): Transport {
return new Truck();
}
}
class SeaLogistics extends Logistics {
createTransport(): Transport {
return new Ship();
}
}
let logistics: Logistics = new RoadLogistics();
logistics.planDelivery();
logistics = new SeaLogistics();
logistics.planDelivery();
interface Transport {
void deliver();
}
class Truck implements Transport {
public void deliver() {
System.out.println("Доставка грузов по суше на грузовике.");
}
}
class Ship implements Transport {
public void deliver() {
System.out.println("Доставка товаров по морю на корабле.");
}
}
abstract class Logistics {
abstract Transport createTransport();
void planDelivery() {
createTransport().deliver();
}
}
class RoadLogistics extends Logistics {
Transport createTransport() {
return new Truck();
}
}
class SeaLogistics extends Logistics {
Transport createTransport() {
return new Ship();
}
}
public class Program {
public static void main(String[] args) {
Logistics logistics = new RoadLogistics();
logistics.planDelivery();
logistics = new SeaLogistics();
logistics.planDelivery();
}
}
interface Transport {
fun deliver()
}
class Truck : Transport {
override fun deliver() = println("Доставка грузов по суше на грузовике.")
}
class Ship : Transport {
override fun deliver() = println("Доставка товаров по морю на корабле.")
}
abstract class Logistics {
abstract fun createTransport(): Transport
fun planDelivery() = createTransport().deliver()
}
class RoadLogistics : Logistics() {
override fun createTransport(): Transport = Truck()
}
class SeaLogistics : Logistics() {
override fun createTransport(): Transport = Ship()
}
fun main() {
var logistics: Logistics = RoadLogistics()
logistics.planDelivery()
logistics = SeaLogistics()
logistics.planDelivery()
}
Плюсы и минусы
| Плюсы | Минусы |
|---|---|
| Избавляет от жёстких зависимостей между создателем и продуктами | Увеличивает количество классов в программе |
| Упрощает добавление новых продуктов | Требует создания иерархии классов для каждого нового продукта |
| Следует принципу открытости/закрытости (OCP) | Иногда кажется избыточным для простых задач |
Заключение
Factory Method — один из самых распространённых порождающих паттернов. Он помогает разделить логику создания объектов и их использование, делая систему более гибкой и устойчивой к изменениям.