Что такое паттерн Factory Method и как он отличается от Simple Factory?

«Что такое паттерн Factory Method и как он отличается от Simple Factory?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Ключевая идея: Класс не знает, объекты какого конкретного класса он должен создать. Эта ответственность переносится на подклассы.

Реализация (классический пример с Creator и Product):

// 1. Интерфейс Продукта
interface Transport {
    void deliver();
}

// 2. Конкретные Продукты
class Truck implements Transport {
    @Override
    public void deliver() {
        System.out.println("Delivering by land in a truck.");
    }
}

class Ship implements Transport {
    @Override
    public void deliver() {
        System.out.println("Delivering by sea in a ship.");
    }
}

// 3. Абстрактный Создатель (Creator) с фабричным методом
abstract class Logistics {
    // Фабричный метод (может быть абстрактным или иметь реализацию по умолчанию)
    public abstract Transport createTransport();

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

// 4. Конкретные Создатели переопределяют фабричный метод
class RoadLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Truck(); // Создаёт конкретный продукт
    }
}

class SeaLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Ship(); // Создаёт другой конкретный продукт
    }
}

// 5. Клиентский код
public class Client {
    public static void main(String[] args) {
        Logistics logistics;

        // Конфигурация (может зависеть от внешних условий)
        String env = "sea";
        if ("sea".equals(env)) {
            logistics = new SeaLogistics();
        } else {
            logistics = new RoadLogistics();
        }

        logistics.planDelivery(); // Будет использован Ship или Truck
    }
}

Отличие от Simple Factory (Простая фабрика):

Аспект Simple Factory Factory Method
Структура Один класс-фабрика с методом, содержащим switch или if-else. Абстрактный Creator и его подклассы, каждый из которых создаёт свой продукт.
Принцип OCP Нарушает OCP. Для добавления нового типа нужно изменять код фабрики. Соответствует OCP. Новый тип продукта добавляется через новый подкласс Creator.
Гибкость Менее гибкий. Вся логика создания в одном месте. Более гибкий. Позволяет подклассам решать, что создавать.
Сложность Проще для понимания и реализации. Сложнее из-за иерархии классов.

Пример Simple Factory для сравнения:

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");

Когда использовать Factory Method:

  • Когда классу заранее неизвестно, объекты каких подклассов ему нужно создавать.
  • Когда вы хотите, чтобы создание объекта было делегировано подклассам.
  • Для реализации фреймворков, где библиотечный код должен работать с пользовательскими классами (как в Spring BeanFactory).