Factory — obyekt yaratish tafsilotlarini caller’dan yashirib, kerakli tur yoki konfiguratsiyadagi instance qaytaradigan dasturiy konstruksiya. Testlashda factory valid test obyektlari va bog‘langan ma’lumotlarni ixcham yaratish uchun ishlatiladi. Atama Factory Method, Abstract Factory va test data factory kabi bir-biriga yaqin, ammo turli ko‘rinishlarni qamrab oladi.
Yaratish logikasini ajratish
Constructor ko‘p parametr, dependency tanlash yoki environmentga bog‘liq qaror talab qilsa, caller har joyda shu tafsilotni takrorlamaydi. Factory meaningful input olib, concrete classni tanlaydi va invariantga mos obyekt qaytaradi.
def create_payment_gateway(kind, config):
if kind == "sandbox":
return SandboxGateway(config)
return LiveGateway(config)
Factory service locatorga aylanmasligi kerak. U yashirin global dependencylarni olib, obyekt graphni istalgan joyda yaratib yuborsa test va ownership noaniq bo‘ladi. Composition root yaratish zanjirini markazlashtiradi.
Factory Method
Factory Method base class yoki interface’da yaratish metodini belgilab, subclassga concrete productni tanlash imkonini beradi. Caller product interface bilan ishlaydi. Bu inheritancega tayangan pattern; oddiy standalone factory function bilan aynan bir xil emas.
Abstract Factory o‘zaro mos productlar oilasini yaratadi, masalan platformaga mos Button va Window. Client concrete class nomini bilmaydi. Dependency injection container ham object graph yaratishi mumkin, lekin uning scope va lifecycle boshqaruvi kengroq.
Test data factory
Test factory model uchun ma’noli valid defaultlar beradi:
user = UserFactory(active=True)
Test faqat scenario uchun muhim active qiymatini ko‘rsatadi. Schema’ga yangi majburiy field qo‘shilsa default bir joyda yangilanadi. Bu yuzlab fixture’ni qo‘lda tuzatishni kamaytiradi.
Default qiymatlar test natijasiga yashirin ta’sir qilmasligi kerak. Masalan, country="US" defaulti soliq testini bexosdan bir mamlakatga bog‘laydi. Business jihatdan muhim field testda aniq beriladi.
Trait va bog‘lanishlar
Factory trait “premium”, “expired” yoki “with_orders” kabi holat kombinatsiyasini yaratishi mumkin. Traitlar bir-biriga zid bo‘lsa precedence aniq. Juda ko‘p trait factoryni yangi domain languagega aylantirib, real modelni yashirishi mumkin.
Bog‘langan obyekt subfactory orqali yaratiladi. OrderFactory user va item yaratishi mumkin, ammo test mavjud userni uzatsa yangisini yaratmaydi. Circular relation va katta graph performancega ta’sir qiladi.
Uniqueness va parallel test
Email kabi unique field sequence yoki UUID bilan yaratiladi. Global process counter parallel workerlar orasida to‘qnashishi mumkin; worker ID yoki UUID ishlatiladi. Deterministik test uchun random seed saqlanadi, lekin uniqueness database constraint bilan ham tekshiriladi.
Factory obyektni faqat memoryda build qilishi yoki databasega create qilishi mumkin. Test qaysi strategiyani ishlatayotganini biladi; keraksiz persistence unit testni sekinlashtiradi.
Factory va builder
Factory odatda tayyor valid obyektni bitta chaqiruvda qaytaradi. Builder esa parametrlarni bosqichma-bosqich yig‘ib, build()da obyekt yaratadi. Ko‘p optional qiymat va o‘qilishi kerak bo‘lgan scenario’da builder qulay; oddiy modelda factory qisqaroq. Test data builder defaultlarni saqlashi, ammo invalid obyekt kerak bo‘lsa validationni ataylab chetlash yo‘lini aniq ajratishi mumkin.
Lifecycle
Factory har chaqiruvda yangi instance, singleton yoki pooldan obyekt qaytarishi mumkin. Bu contractda ko‘rsatiladi. Caller yangi deb o‘ylab shared mutable instance olsa testlar bir-biriga ta’sir qiladi. Dependency injection container transient, scoped va singleton lifecycle’ni boshqaradi.
Async factory
Yaratish uchun network yoki file I/O kerak bo‘lsa async factory ishlatiladi. Constructor async bo‘la olmaydigan tillarda await Client.create() patterni uchraydi. Qisman yaratilgan obyekt callerga chiqmasligi, xatoda ochilgan resurslar yopilishi kerak.
Registratsiya modeli
Plugin factory type nomini constructor funksiyasiga bog‘lovchi registry ishlatishi mumkin. Noma’lum type aniq xato beradi. Global mutable registry testda tozalanmasa registrationlar sizadi; har application context uchun registry instance’i yoki immutable mapping ishlatiladi.
Bog‘liq tushunchalar
Factory Method, Abstract Factory, Test data builder, Fixture, Dependency injection, Object creation