Bosh sahifa Wiki Adapter Pattern

Adapter Pattern

Adapter Pattern — bir class yoki tizim interface’ini client kutayotgan boshqa interface’ga moslashtiradigan structural design pattern. Adapter mos kelmaydigan komponentlarni ularning ichki kodini o‘zgartirmasdan birga ishlatishga yordam beradi.

Adapter elektr qurilmasi uchun ulagich adapteriga o‘xshaydi: manba va iste’molchi o‘zgarmaydi, ular orasida moslashtiruvchi qatlam paydo bo‘ladi.

Muammo

Application quyidagi interface’ni kutishi mumkin:

class PaymentGateway:
    def pay(self, amount: int) -> str:
        ...

Tashqi provider esa boshqa method beradi:

provider.create_charge(summa, currency)

Clientni provider API’ga qattiq bog‘lash o‘rniga adapter yaratiladi.

Target

Targetclient kutayotgan interface.

Client faqat shu contract bilan ishlaydi.

Masalan:

pay(amount)
refund(transaction_id)
status(transaction_id)

Target domain tiliga mos bo‘lishi kerak.

Adaptee

Adaptee — mavjud, ammo interface’i clientga mos kelmaydigan class yoki service.

Bu:

  • legacy class;
  • uchinchi tomon SDK;
  • eski API;
  • boshqa format;
  • boshqa protocol

bo‘lishi mumkin.

Adaptee kodini o‘zgartirish imkonsiz yoki xavfli bo‘lishi mumkin.

Adapter

Adapter Target interface’ni amalga oshiradi va chaqiriqlarni Adaptee formatiga tarjima qiladi.

U:

  • method nomini moslashtiradi;
  • argumentlarni o‘zgartiradi;
  • return qiymatni domain formatiga aylantiradi;
  • exceptionni map qiladi;
  • unit conversion bajaradi.

Adapter business qoidalarni ortiqcha yig‘masligi kerak.

Object adapter

Object adapter composition’dan foydalanadi.

class ProviderAdapter(PaymentGateway):
    def __init__(self, provider):
        self.provider = provider

Adapter ichida adaptee instance saqlanadi.

Bu ko‘p tillarda qulay va moslashuvchan.

Bir adaptee o‘rniga boshqasini inject qilish mumkin.

Class adapter

Class adapter inheritance orqali Target va Adaptee’ni bog‘laydi.

Bu multiple inheritance mavjud tillarda ishlashi mumkin.

Kamchiligi — konkret classga qattiq bog‘lanish va inheritance cheklovlari.

Composition asosidagi object adapter ko‘proq qo‘llanadi.

Two-way adapter

Ba’zi holatda ikki interface orasida ikki tomonlama moslashtirish kerak.

Adapter Target chaqiriqlarini Adaptee’ga, Adaptee formatini esa Targetga aylantiradi.

Bu murakkablikni oshiradi va barcha operationlar simmetrik bo‘lmasligi mumkin.

Data mapping

Adapter field nomlarini moslashtiradi.

Masalan:

first_name → givenName
created_at → createdAt
amount_uzs → amount

Mappingda:

  • missing field;
  • null;
  • enum;
  • date;
  • timezone;
  • precision

aniq boshqariladi.

Type conversion

Tashqi tizim decimal string qaytarishi, application esa integer tiyin ishlatishi mumkin.

Adapter conversionni markazlashtiradi.

Pul qiymatida floating-point conversiondan qochiladi.

Unit va rounding qoidalari hujjatlashtiriladi.

Error mapping

Provider exceptionlari domain errorlariga aylantiriladi.

Masalan:

ProviderTimeout → PaymentTemporaryError
InvalidCard → PaymentRejected
Unauthorized → ProviderConfigurationError

Client tashqi SDK exceptionlarini bilmaydi.

Retry faqat vaqtinchalik xatolarga qo‘llanadi.

Legacy integration

Eski class methodlari yangi arxitektura contractiga mos kelmasligi mumkin.

Adapter legacy kodni to‘liq qayta yozmasdan yangi service ichida ishlatadi.

Bu migrationni bosqichma-bosqich bajarishga yordam beradi.

Keyinchalik legacy component olib tashlansa adapter ham o‘chiriladi.

Tashqi API adapteri

Har tashqi provider uchun alohida adapter yaratilishi mumkin.

Masalan:

ClickAdapter
PaymeAdapter
MockPaymentAdapter

Application bir xil PaymentGateway interface’iga tayanadi.

Provider almashishi domain code’ni o‘zgartirmaydi.

Adapter va Facade

Adapter interface’ni boshqa interface’ga moslashtiradi.

Facade esa murakkab subsystem uchun soddalashtirilgan umumiy interface beradi.

Facade ichida bir nechta adapter bo‘lishi mumkin.

Adapter va Decorator

Adapter interface’ni o‘zgartiradi.

Decorator odatda shu interface’ni saqlab, yangi xatti-harakat qo‘shadi.

Masalan:

Adapter va Proxy

Proxy odatda shu interface’ni saqlaydi va accessni boshqaradi.

Adapter esa client va adaptee interface’lari mos kelmaganda tarjima qiladi.

Amalda bir class ikkala vazifani qisman bajarishi mumkin, ammo asosiy niyat farq qiladi.

Test

Adapter unit testlari quyidagilarni tekshiradi:

  • argument mapping;
  • response mapping;
  • error mapping;
  • null;
  • timeout;
  • currency va timezone;
  • providerning yangi versiyasi.

Tashqi SDK integration testi ham kerak.

Contract test

Barcha adapterlar umumiy Target contractga mosligini bir xil test suite bilan tekshirish mumkin.

Masalan, har payment adapter:

  • musbat amount qabul qiladi;
  • transaction ID qaytaradi;
  • vaqtinchalik xatoni bir xil domain errorga aylantiradi.

Bu providerlar orasidagi xatti-harakatni yaqinlashtiradi.

Afzalliklari

Adapter:

Kamchiliklari

Ko‘p adapter qatlamlari debuggingni qiyinlashtirishi mumkin.

Tashqi API imkoniyatlari Target interface’da yo‘qolishi ehtimoli bor.

Universal interface barcha provider farqlarini yashira olmasligi mumkin.

Default qiymat va yo‘q field

Tashqi provider ayrim fieldni yubormasligi mumkin.

Adapter missing, null va bo‘sh string holatlarini bir xil deb qabul qilmasligi kerak.

Masalan, middle_name yo‘qligi bilan bo‘sh qiymatning business ma’nosi farq qilishi mumkin.

Mapping defaultlari domain qoidasi asosida qo‘llanadi.

Capability farqi

Barcha provider bir xil imkoniyatga ega emas.

Bitta payment provider partial refundni, boshqasi faqat full refundni qo‘llashi mumkin.

Target interface eng kichik umumiy denominatorga tushib qolmasligi uchun capability explicit ko‘rsatiladi yoki alohida interface’lar yaratiladi.

Version compatibility

Adapter tashqi SDK yoki API versioniga bog‘langan bo‘ladi.

Provider yangi required field qo‘shsa contract test xatoni erta ko‘rsatadi.

Version upgrade alohida adapterda sinovdan o‘tkazilib, keyin traffic bosqichma-bosqich yangi variantga o‘tkaziladi.

Bog‘liq tushunchalar

Structural pattern, Target, Adaptee, Object adapter, Interface, Facade, Decorator, Proxy, Legacy system, Integration layer