Что такое паттерн Factory (Фабрика)?

Ответ

Factory Method — это порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов.

Цель: Инкапсулировать логику создания объектов, делая систему независимой от конкретных классов продуктов.

Преимущества:

  • Изоляция кода создания: Клиентский код работает с интерфейсом, а не с конкретными классами.
  • Принцип открытости/закрытости: Легко добавить новый тип продукта, создав новый подкласс фабрики.
  • Упрощение тестирования: Фабрику можно подменить заглушкой (Mock).

Пример на Java:

// 1. Общий интерфейс продукта
interface Transport {
    void deliver();
}

// 2. Конкретные продукты
class Truck implements Transport {
    @Override
    public void deliver() {
        System.out.println("Доставка груза по дороге.");
    }
}

class Ship implements Transport {
    @Override
    public void deliver() {
        System.out.println("Доставка груза по морю.");
    }
}

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

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

// 4. Конкретные создатели
class RoadLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Truck();
    }
}

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

// 5. Использование
public class Demo {
    public static void main(String[] args) {
        Logistics logistics = new RoadLogistics();
        logistics.planDelivery(); // Создаст Truck и вызовет его deliver()
    }
}

Ответ 18+ 🔞

Да ты посмотри, какой народ безмозглый, блядь! Опять про эти ваши паттерны. Ну ладно, разберём, как есть.

Вот есть у тебя, допустим, задача — создавать объекты. А объекты-то разные, ёпта! Грузовик, корабль, самолёт. И логика создания у них — пиздец какая разная. Можно, конечно, везде натыкать new Truck() и new Ship(), но тогда твой код превратится в такой монолит, что его потом раздолбать будет — овердохуища работы.

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

Нахуя это надо?

  • Клиентский код не парится. Ему похуй, грузовик там или подводная лодка. Он знает только, что у объекта есть метод deliver(), и он его вызывает. Всё.
  • Легко добавить новую хуйню. Надо новый транспорт? Создаёшь новый класс продукта и новый класс логистики для него. Старый код даже не чихнёт. Принцип открытости/закрытости в действии, блядь!
  • Тестировать — одно удовольствие. Подсовываешь в тестах свою фабрику-заглушку, которая создаёт не настоящий грузовик, а какую-нибудь муляжную хрень, и проверяешь логику. Красота!

Смотри, как это в коде выглядит, на примере доставки:

// 1. Интерфейс для всего, что может доставлять
interface Transport {
    void deliver();
}

// 2. Конкретные виды доставки
class Truck implements Transport {
    @Override
    public void deliver() {
        System.out.println("Тащу твой хлам по дороге, как последний лох.");
    }
}

class Ship implements Transport {
    @Override
    public void deliver() {
        System.out.println("Плыву по морю, волны бьют, доставка долгая, терпи, мудак.");
    }
}

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

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

// 4. Конкретные фабрики. Каждая знает, какую конкретную хуйню создавать.
class RoadLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Truck(); // Дорога? Значит, грузовик!
    }
}

class SeaLogistics extends Logistics {
    @Override
    Transport createTransport() {
        return new Ship(); // Море? Окей, кораблик.
    }
}

// 5. Использование
public class Demo {
    public static void main(String[] args) {
        Logistics logistics = new RoadLogistics(); // Говорим: "Хочу дорожную логистику!"
        logistics.planDelivery(); // А внутри само создаст грузовик и пошлёт его в путь. В рот меня чих-пых!
    }
}

Вот и вся философия. Вместо того чтобы самому везде лезть с new, ты делегируешь это дело специальному классу. Получается аккуратно, расширяемо и без лишней головной боли. Ну а если не использовать — потом сам будешь, как Герасим, только «Му-му» говорить, когда систему расширять придётся.