В чем разница между паттернами Factory и Factory Method?

Ответ

Factory (Фабрика) — это общее название для группы порождающих паттернов, которые инкапсулируют логику создания объектов. Чаще всего под "простой фабрикой" понимают Simple Factory (статический метод-фабрика), который не является отдельным паттерном из GoF, но широко используется.

Factory Method (Фабричный метод) — это конкретный паттерн проектирования из книги GoF, где создание объекта делегируется подклассам.

1. Simple Factory (Простая фабрика)

Это класс с методом (часто статическим), который на основе входного параметра создает и возвращает объект нужного типа.

interface Transport {
    void deliver();
}

class Truck implements Transport {
    public void deliver() { System.out.println("Deliver by land"); }
}
class Ship implements Transport {
    public void deliver() { System.out.println("Deliver by sea"); }
}

// Простая фабрика (не GoF паттерн)
class TransportFactory {
    public static Transport createTransport(String type) {
        return switch (type.toLowerCase()) {
            case "truck" -> new Truck();
            case "ship" -> new Ship();
            default -> throw new IllegalArgumentException("Unknown transport");
        };
    }
}
// Использование
Transport t = TransportFactory.createTransport("truck");
t.deliver();

Недостаток Simple Factory: При добавлении нового типа (Plane) необходимо изменять метод createTransport, нарушая принцип открытости/закрытости (OCP).

2. Factory Method (Фабричный метод, паттерн GoF)

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

// Абстрактный создатель (Creator)
abstract class Logistics {
    // Фабричный метод
    abstract Transport createTransport();

    // Бизнес-логика, использующая продукт
    public void planDelivery() {
        Transport t = createTransport(); // Вызов фабричного метода
        t.deliver();
    }
}

// Конкретные создатели
class RoadLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Truck(); // Решает, какой объект создать
    }
}

class SeaLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Ship();
    }
}

// Использование
Logistics logistics = new RoadLogistics();
logistics.planDelivery(); // Будет создан и использован Truck
Ключевые отличия: Аспект Simple Factory Factory Method (GoF)
Суть Класс с методом, создающим объекты. Делегирование создания подклассам через абстрактный метод.
Расширяемость Нарушает OCP (требует изменения фабрики). Соблюдает OCP (новый тип = новый подкласс Creator).
Связность Централизованная логика создания. Логика создания распределена по иерархии классов.
Цель Сокрытие логики инстанцирования. Позволить подклассам решать, какой объект создавать.

Вывод: Factory Method — это более гибкий и полиморфный паттерн, который следует принципам OCP, в то время как Simple Factory — это простой и полезный идиоматический прием для инкапсуляции создания объектов.

Ответ 18+ 🔞

Слушай, а давай разберёмся, что за фабрики такие, а то все ими кидаются, а толком объяснить не могут. Вот представь, что ты на стройке, и тебе нужен инструмент. Можно, конечно, самому каждый раз бегать на склад, искать нужную дрель, но это же, блядь, неудобно! Вот для этого и придумали фабрики — чтобы тебе просто сказали «дай дрель», а тебе её уже принесли, готовую.

Simple Factory (Простая фабрика) — это как будто у тебя есть один универсальный снабженец Вася. Ты ему кричишь: «Вася, дай мне грузовик!». А Вася такой: «Ща, браток», — идёт на склад и привозит тебе этот самый грузовик. Всё просто, понятно, но есть одна, сука, проблема. Если завтра тебе понадобится самолёт, а Вася про самолёты нихуя не знает, придётся его самого переучивать, лезть ему в мозги и менять его инструкции. Нарушается принцип «открытости/закрытости» — чтобы добавить что-то новое, надо ковырять существующий код. Не очень-то гибко, правда?

// Вот этот Вася, наш снабженец
class TransportFactory {
    public static Transport createTransport(String type) {
        if (type.equalsIgnoreCase("truck")) {
            return new Truck(); // Привёз грузовик
        } else if (type.equalsIgnoreCase("ship")) {
            return new Ship(); // Привёг корабль
        } else {
            throw new IllegalArgumentException("Чё те надо, мудила? Такого у нас нет!");
        }
    }
}
// А пользоваться просто:
Transport t = TransportFactory.createTransport("truck");
t.deliver(); // Поехали!

Factory Method (Фабричный метод, тот самый паттерн из книжки) — это уже поумнее. Тут нет одного Васю. Тут у тебя есть начальник отдела логистики, который говорит: «Ребята, план доставки у нас такой-то, а кто и на чём повезёт — решайте сами на местах!».

То есть создаётся абстрактный класс-родитель, который объявляет: «Эй, потомки, у вас будет метод createTransport(), но как вы его реализуете — это ваши, блядь, проблемы!».

// Абстрактный начальник, который знает план, но не лезет в детали
abstract class Logistics {
    // Вот он, фабричный метод! Конкретики нет.
    abstract Transport createTransport();

    // А вот бизнес-логика, которая этим пользуется
    public void planDelivery() {
        Transport t = createTransport(); // Надеется на потомков
        t.deliver();
    }
}

// А вот конкретные исполнители. Дорожники знают своё дело.
class RoadLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Truck(); // «Нам грузовик подавай!»
    }
}

// Моряки — своё.
class SeaLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Ship(); // «Нам корабль, ёпта!»
    }
}

// Используем:
Logistics logistics = new RoadLogistics();
logistics.planDelivery(); // Всё работает, создался Truck

Так в чём, блядь, разница, спросишь ты? Да в том, кто принимает решение!

  • Simple Factory: Решение принимает один центральный орган (наш Вася-фабрика) на основе какого-то параметра (строки, enum). Добавить новый тип — пойти и переписать Васину инструкцию. Нарушается OCP.
  • Factory Method: Решение принимают конкретные классы-наследники. Каждый сам решает, что ему создавать. Хочешь добавить воздушную логистику? Просто создаёшь новый класс AirLogistics, который возвращает new Plane(). Основной класс Logistics и остальной код даже не узнают об этом! Это и есть соблюдение OCP — система открыта для расширения, но закрыта для модификации.

Вывод, ёпта: Simple Factory — это просто удобная обёртка для создания объектов, как костыль, который всем виден. А Factory Method — это уже продуманная архитектура, где создание объектов делегировано полиморфно, и система может расти, не ломая уже работающее. Выбирай, что тебе больше подходит, но не путай одно с другим, а то получится пиздопроебищно!