Bosh sahifa Wiki Decorator Pattern

Decorator Pattern

Decorator Pattern — obyektga runtime vaqtida yangi xatti-harakat qo‘shadigan structural design pattern. Decorator original obyekt bilan bir xil interface’ni saqlaydi va chaqiriqni ichki obyektga uzatishdan oldin yoki keyin qo‘shimcha ish bajaradi.

Decorator inheritance orqali ko‘plab subclass yaratmasdan funksiyalarni kombinatsiya qilishga yordam beradi.

Component

Componentclient ishlatadigan umumiy interface.

Masalan:

class Storage:
    def save(self, key, data):
        ...

Concrete component haqiqiy storage amalini bajaradi.

Decorator ham ayni interface’ni amalga oshiradi.

Concrete component

Asosiy xatti-harakatni bajaradigan obyekt.

Misollar:

Decorator shu obyektni ichida saqlaydi.

Base decorator

Base decorator component reference’ini qabul qiladi.

class StorageDecorator(Storage):
    def __init__(self, wrapped: Storage):
        self.wrapped = wrapped

Default implementation chaqiriqni ichki componentga uzatadi.

Concrete decorator kerakli qo‘shimcha xatti-harakatni qo‘shadi.

Concrete decorator

Masalan, encryption decorator:

save
→ data’ni shifrlash
→ wrapped.save

Compression decorator:

save
→ data’ni siqish
→ wrapped.save

Logging decorator:

save
→ vaqtni o‘lchash
→ wrapped.save
→ log yozish

Runtime kombinatsiya

Decoratorlar bir-biriga o‘raladi.

Logging(
    Encryption(
        Compression(
            FileStorage
        )
    )
)

Har qatlam bir vazifani bajaradi.

Kombinatsiya runtime’da tanlanishi mumkin.

Tartib

Decoratorlar tartibi natijaga ta’sir qiladi.

Masalan:

compress → encrypt

odatda:

encrypt → compress

dan samaraliroq, chunki encrypted data yaxshi siqilmaydi.

Logging encryptiondan oldin yoki keyin bo‘lsa logdagi ma’lumot farq qiladi.

Tartib explicit bo‘lishi kerak.

Inheritance bilan muammo

Agar funksiyalar inheritance orqali kombinatsiya qilinsa:

EncryptedStorage
CompressedStorage
LoggedStorage
EncryptedCompressedStorage
LoggedEncryptedStorage
...

subclasslar soni tez ko‘payadi.

Decorator kichik mustaqil xatti-harakatlarni erkin kombinatsiya qiladi.

Open/Closed Principle

Mavjud component kodini o‘zgartirmasdan yangi decorator qo‘shiladi.

Bu classni extension uchun ochiq, modification uchun yopiq saqlashga yordam beradi.

Biroq interface o‘zgarsa barcha decoratorlar yangilanishi kerak.

Logging decorator

Service call davomiyligi va natijasini log qiladi.

U:

ni yozishi mumkin.

Secret va personal data logga kiritilmaydi.

Retry decorator

Vaqtinchalik xatoda operationni qayta chaqiradi.

Retry:

bilan boshqariladi.

Non-idempotent operationga ko‘r-ko‘rona retry duplicate side effect yaratishi mumkin.

Cache decorator

Read operation natijasini cache qiladi.

Jarayon:

  1. cache key yaratish;
  2. cache’dan qidirish;
  3. miss bo‘lsa wrapped service’ni chaqirish;
  4. natijani cache’ga yozish.

Cache invalidation va TTL alohida boshqariladi.

Authorization decorator

Chaqiriqdan oldin user permissionini tekshiradi.

Bu cross-cutting concernni asosiy business classdan ajratadi.

Lekin object-level authorization uchun operation argumentlari to‘g‘ri tekshirilishi kerak.

Metrics decorator

Call count, latency va error metriclarini yig‘adi.

Decorator label cardinality’ni nazorat qiladi.

Request ID yoki user IDni metric label sifatida ishlatish series sonini keskin oshiradi.

Decorator va Middleware

Middleware request pipeline darajasida ishlaydi.

Decorator ma’lum interface yoki obyekt chaqirig‘ini o‘raydi.

Ikki yondashuvning maqsadi o‘xshash bo‘lishi mumkin, ammo qo‘llanish nuqtasi farq qiladi.

Decorator va Proxy

Ikkalasi ham bir xil interface bilan wrapper ishlatadi.

Decoratorning niyati xatti-harakat qo‘shish va kombinatsiya qilish.

Proxy’ning niyati access, lifecycle, remote call yoki lazy loadingni boshqarish.

Decorator va Adapter

Decorator interface’ni saqlaydi.

Adapter interface’ni boshqa ko‘rinishga aylantiradi.

Agar wrapper method nomlarini o‘zgartirsa u adapterga yaqinlashadi.

Transparent decorator

Client wrapped obyekt yoki decorator ekanini bilmasdan ishlaydi.

Buning uchun decorator Component contractni to‘liq saqlashi kerak.

Agar decorator yangi public methodlar qo‘shsa client concrete type’ni bilishi kerak bo‘ladi va transparency kamayadi.

State

Decorator o‘z state’iga ega bo‘lishi mumkin.

Masalan:

Thread-safe ishlash kerak bo‘lsa shared state synchronization talab qiladi.

Test

Har decorator alohida fake component bilan test qilinadi.

Tekshiriladi:

  • wrapped method chaqirildimi;
  • argument o‘zgardimi;
  • return saqlandimi;
  • error qanday tarqaldi;
  • tartib;
  • side effect soni.

Bir nechta decorator kombinatsiyasi uchun integration test ham kerak.

Kamchiliklari

Ko‘p wrapper stack trace va debuggingni murakkablashtiradi.

Tartib xatosi yashirin semantik farq yaratadi.

Object identity va equality wrapped obyekt bilan mos kelmasligi mumkin.

Decorator factory

Qaysi decoratorlar qaysi tartibda qo‘llanishini markazlashtirish uchun factory yoki composition root ishlatiladi.

Masalan:

base client
→ metrics
→ retry
→ circuit breaker
→ authentication

Client bu stackni qo‘lda yig‘maydi.

Tartib bitta joyda test qilinadi.

Return qiymatni saqlash

Decorator wrapped method return qiymati va exception semantikasini saqlashi kerak.

Masalan, logging decorator natijani o‘zgartirib yubormaydi.

Cache decorator esa contract ruxsat bersa stale yoki serialized qiymat qaytarishi mumkin.

Bu farq documentationda aniq ko‘rsatiladi.

Async decorator

Asynchronous methodni o‘raydigan decorator await, cancellation va timeoutni to‘g‘ri uzatishi kerak.

Cancellation exceptionini oddiy xato deb retry qilish operationni bekor qilib bo‘lmas holatga olib keladi.

Context va trace metadata ham wrapped callga uzatiladi.

Konfiguratsiya ko‘rinishi

Production’da decoratorlar qaysi tartibda yig‘ilgani startup log yoki dependency graph’da ko‘rsatilishi mumkin.

Bu yashirin wrapper zanjirini tahlil qilishni osonlashtiradi.

Bog‘liq tushunchalar

Structural pattern, Component, Wrapper, Composition, Proxy, Adapter, Middleware, Open-Closed Principle, Cross-cutting concern