В чем разница между паттернами Builder и Factory и для чего они нужны
Что проверяют
Понимаете ли вы, что оба паттерна про создание объектов, но решают разные задачи: Factory выбирает, какой объект создать, Builder отвечает, как собрать сложный объект по шагам. Следом обычно спрашивают, нужен ли Builder в Swift, где есть параметры по умолчанию.
Как отвечать
Начните с разницы в одну фразу, затем разберите каждый:
- Factory: прячет от вызывающего кода конкретный тип. Клиент получает протокол и не знает, какой класс за ним стоит. Назовите разновидности: простая фабрика (статический метод), Factory Method из GoF (подкласс решает, что создать) и Abstract Factory (семейство связанных объектов, например набор компонентов под тему);
- Builder: пошаговая сборка объекта с большим числом необязательных параметров и проверкой в финальном
build(). Результат часто неизменяемый.
Примеры из iOS звучат убедительнее абстрактных кнопок. Фабрика: сборка модуля экрана в VIPER или координаторе, где метод вроде makeProfileModule() создаёт UIViewController, презентер и сервисы и связывает их. Статические фабричные методы есть и в UIKit: UIButton.Configuration.filled(), UIFont.preferredFont(forTextStyle:). Builder: конструирование URLRequest в сетевом слое, где заголовки, тело и параметры добавляются по шагам.
Про Swift скажите честно: инициализатор с параметрами по умолчанию и memberwise init у структур закрывают большую часть случаев, ради которых Builder придумывали в Java. Он оправдан, когда сборка идёт в несколько этапов, есть правила согласованности полей или объект собирают разные части кода. В Swift-стиле методы билдера у структуры возвращают изменённую копию, по духу это похоже на цепочку модификаторов SwiftUI.
Где спотыкаются
Путают Factory Method и Abstract Factory или называют фабрикой любую функцию, которая возвращает объект.
Пишут фабрику, которая принимает строку "iOS" и возвращает опционал. Тип стоит выбирать через enum: компилятор проверит все варианты, а nil на опечатку исчезнет.
Путают Builder с @resultBuilder. Второй это механизм для DSL, на нём построен ViewBuilder в SwiftUI, к порождающему паттерну он отношения почти не имеет.