← Назад к вопросам
Что такое паттерн Фабричный метод?
1.0 Junior🔥 181 комментариев
#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое паттерн Фабричный метод?
Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который позволяет создавать объекты без привязки кода к конкретным классам. Вместо прямого создания объекта через конструктор (new), ты используешь специальный метод, который решает какой класс инстанцировать. Это обеспечивает гибкость и упрощает добавление новых типов объектов в будущем.
Проблема без паттерна
// Плохо — жёсткая привязка к конкретным классам
class OrderProcessor {
fun processPayment(type: String): PaymentService {
return when (type) {
"stripe" -> StripePaymentService()
"paypal" -> PayPalPaymentService()
"apple_pay" -> ApplePayService()
else -> throw IllegalArgumentException("Unknown type")
}
}
}
Проблемы:
- Код разбросан по приложению
- Сложно добавить новый способ оплаты
- Нарушается принцип Open/Closed (открыта для модификации, закрыта для расширения)
- Тяжело тестировать
Решение с Factory Method
// 1. Интерфейс для создаваемых объектов
interface PaymentService {
fun pay(amount: Double)
}
// 2. Конкретные реализации
class StripePaymentService : PaymentService {
override fun pay(amount: Double) {
println("Paying $amount via Stripe")
}
}
class PayPalPaymentService : PaymentService {
override fun pay(amount: Double) {
println("Paying $amount via PayPal")
}
}
class ApplePayService : PaymentService {
override fun pay(amount: Double) {
println("Paying $amount via Apple Pay")
}
}
// 3. Абстрактный фабрикант
abstract class PaymentFactory {
abstract fun createPaymentService(): PaymentService
}
// 4. Конкретные фабрики
class StripePaymentFactory : PaymentFactory() {
override fun createPaymentService() = StripePaymentService()
}
class PayPalPaymentFactory : PaymentFactory() {
override fun createPaymentService() = PayPalPaymentService()
}
class ApplePayFactory : PaymentFactory() {
override fun createPaymentService() = ApplePayService()
}
// 5. Использование
class OrderProcessor {
fun processPayment(factory: PaymentFactory, amount: Double) {
val paymentService = factory.createPaymentService()
paymentService.pay(amount)
}
}
Более элегантное решение с функциями
В Kotlin можно использовать более простой подход:
object PaymentServiceFactory {
private val factories = mutableMapOf<String, () -> PaymentService>()
init {
factories["stripe"] = { StripePaymentService() }
factories["paypal"] = { PayPalPaymentService() }
factories["apple_pay"] = { ApplePayService() }
}
fun create(type: String): PaymentService {
return factories[type]?.invoke()
?: throw IllegalArgumentException("Unknown payment type: $type")
}
fun register(type: String, factory: () -> PaymentService) {
factories[type] = factory
}
}
// Использование
val service = PaymentServiceFactory.create("stripe")
service.pay(99.99)
// Добавление нового способа оплаты в runtime
PaymentServiceFactory.register("cryptocurrency") { CryptoPaymentService() }
Пример в Android: Dialog Factory
object DialogFactory {
fun createDialog(
context: Context,
type: DialogType
): AlertDialog {
val builder = AlertDialog.Builder(context)
return when (type) {
DialogType.CONFIRMATION -> {
builder
.setTitle("Confirm Action")
.setPositiveButton("OK") { _, _ -> }
.setNegativeButton("Cancel") { _, _ -> }
.create()
}
DialogType.LOADING -> {
builder
.setTitle("Loading...")
.setMessage("Please wait")
.setCancelable(false)
.create()
}
DialogType.ERROR -> {
builder
.setTitle("Error")
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton("OK") { _, _ -> }
.create()
}
}
}
}
enum class DialogType {
CONFIRMATION, LOADING, ERROR
}
// Использование
val dialog = DialogFactory.createDialog(this, DialogType.CONFIRMATION)
dialog.show()
Преимущества паттерна
- Гибкость — легко добавлять новые типы без изменения существующего кода
- Разделение ответственности — логика создания отделена от логики использования
- Тестируемость — можно создать Mock фабрику для тестов
- Следование принципам SOLID — Open/Closed, Dependency Inversion
- Полиморфизм — работаешь с интерфейсом, не с конкретным классом
Когда использовать
- Когда есть иерархия классов и нужно выбирать реализацию в runtime
- Когда логика создания сложная или зависит от конфигурации
- Когда планируешь расширять типы объектов в будущем
- Когда нужна инъекция зависимостей (Dependency Injection)