Observer Pattern — bir obyekt holati o‘zgarganda unga bog‘langan boshqa obyektlarga avtomatik xabar beradigan behavioral design pattern. U publisher va subscriberlar orasidagi to‘g‘ridan-to‘g‘ri bog‘lanishni kamaytiradi.
Pattern event-driven tizimlar, UI, domain event, notification, cache invalidation va reactive modelda keng ishlatiladi.
Subject
Subject yoki publisher observerlar ro‘yxatini saqlaydi.
U odatda quyidagi amallarga ega:
- observer qo‘shish;
- observerni o‘chirish;
- hodisa haqida xabar berish.
Subject observerlarning aniq implementationini bilmaydi. U umumiy interface orqali murojaat qiladi.
Observer
Observer xabar qabul qiladigan interface.
Masalan:
class Observer:
def update(self, event):
...
Concrete observer eventga mos amal bajaradi.
Bir event uchun bir nechta observer bo‘lishi mumkin.
Push modeli
Subject event yoki yangi holatni observerga yuboradi.
notify(event)
Afzalligi — observer qayta query qilmaydi.
Kamchiligi — event payload barcha observerlar uchun ortiqcha katta bo‘lishi mumkin.
Pull modeli
Subject faqat o‘zgarish bo‘lganini bildiradi.
Observer kerakli qiymatni subjectdan o‘zi oladi.
Bu payloadni kichik qiladi.
Ammo observerlar subjectga qayta murojaat qilib ko‘p query yoki qattiq bog‘lanish yaratishi mumkin.
Subscription
Observer subjectga ro‘yxatdan o‘tadi.
haqida ma’lumot saqlashi mumkin.
Subscription handle orqali keyinchalik unsubscribe qilish mumkin.
Unsubscribe
Observer kerak bo‘lmay qolganda ro‘yxatdan chiqariladi.
Aks holda:
- memory leak;
- duplicate notification;
- yopilgan UI componentga callback;
- eskirgan reference
yuz beradi.
Lifecycle bilan subscription lifecycle birga boshqariladi.
Synchronous notification
Subject observerlarni shu call stack ichida chaqiradi.
Afzalligi:
- sodda;
- darhol;
- transactionga yaqin semantika.
Kamchiligi — sekin observer subject operationini bloklaydi.
Bitta observer exceptioni boshqalarga ta’sir qilishi mumkin.
Asynchronous notification
Event queue yoki scheduler orqali keyinroq yetkaziladi.
Afzalligi:
- publisher tez tugaydi;
- observerlar parallel;
- retry;
- isolation.
Kamchiligi:
- eventual consistency;
- duplicate delivery;
- ordering;
- monitoring;
- queue dependency.
Event payload
Yaxshi event quyidagilarni saqlashi mumkin:
- event turi;
- entity ID;
- oldingi va yangi holat;
- vaqt;
- correlation ID;
- source;
- schema version.
Barcha entity obyektini yuborish serialization va privacy muammosini oshiradi.
UI misoli
Button click bo‘lganda bir nechta listener xabar oladi.
Masalan:
- form validation;
- analytics;
- navigation;
- visual state.
UI frameworklar observer modelidan keng foydalanadi.
Component yo‘q qilinganda listenerlar tozalanadi.
Domain event
Order paid holatiga o‘tganda:
- invoice yaratish;
- notification;
- analytics;
- inventory;
- loyalty
observerlari ishlashi mumkin.
Domain model faqat OrderPaid eventini chiqaradi.
Observerlar alohida service’larda yoki bir process ichida bo‘lishi mumkin.
Ordering
Bir nechta observer qaysi tartibda chaqirilishi muhim bo‘lishi mumkin.
Agar observer B observer A natijasiga tayanadigan bo‘lsa ular aslida mustaqil emas.
Bunday dependency explicit workflow yoki orchestrationga ko‘chiriladi.
Observer tartibiga yashirin tayanish fragile dizayn yaratadi.
Error handling
Synchronous modelda observer xatosi uchun siyosat:
- notificationni to‘xtatish;
- qolgan observerlarni davom ettirish;
- barcha xatolarni yig‘ish;
- rollback;
- log.
Asynchronous modelda retry va dead-letter queue ishlatilishi mumkin.
Duplicate event
Network yoki retry sabab observer ayni eventni bir necha marta olishi mumkin.
Event ID va processed registry orqali deduplication qilinadi.
Yoki handler idempotent yoziladi.
Masalan, status = sentga o‘rnatish qayta bajarishga chidamli, ammo balance += 100 ehtiyotkorlik talab qiladi.
Memory leak
Subject observer reference’larini uzoq saqlasa observer garbage collection qilinmaydi.
Weak reference ayrim UI va cache holatlarida yordam berishi mumkin.
Lekin weak reference observerning kutilmaganda yo‘qolishiga ham olib kelishi mumkin.
Event bus
Event bus ko‘p publisher va subscriberlarni markaziy vositachi orqali bog‘laydi.
Publisher observerlarni bevosita bilmaydi.
Bu observer patternning umumlashtirilgan ko‘rinishi.
Global event bus event oqimini topish va debuggingni qiyinlashtirishi mumkin.
Observer va Pub/Sub
Observer ko‘pincha bir process ichida to‘g‘ridan-to‘g‘ri reference bilan ishlaydi.
Publish/Subscribe broker yoki event bus orqali publisher va subscriberlarni yanada ajratadi.
Pub/Sub tarmoq, durability va retry semantikasiga ega bo‘lishi mumkin.
Observer va Mediator
Observer bir publisherdagi o‘zgarishni ko‘p listenerga tarqatadi.
Mediator esa ko‘p component orasidagi murakkab interactionni markazlashtiradi.
Bir UI tizimida ikkalasi birga ishlashi mumkin.
Test
Testlarda:
- observer ro‘yxatdan o‘tdimi;
- kerakli event yuborildimi;
- unsubscribe ishladimi;
- bir necha observer;
- observer exceptioni;
- duplicate event;
- tartib;
- asynchronous retry
tekshiriladi.
Fake observer chaqiriqlarni yozib boradi.
Event filter
Observer barcha eventlarni emas, faqat ma’lum shartga moslarini qabul qilishi mumkin.
Filter subject, event bus yoki observerning o‘zida bajariladi.
Masalan, faqat status=paid bo‘lgan order eventlari invoice observerga yuboriladi.
Filter qoidasi ko‘p joyda takrorlansa semantik farq paydo bo‘lishi mumkin.
Reentrancy
Synchronous observer subjectni qayta o‘zgartirsa notification ichida yana notification boshlanishi mumkin.
Bu recursion, duplicate event va tartib muammosini keltiradi.
Event queue, state guard yoki transaction oxirida publish qilish orqali reentrancy boshqariladi.
Batch notification
Ko‘p kichik o‘zgarishni har safar alohida yuborish qimmat.
Subject transaction yoki vaqt oynasi oxirida bitta umumiy event yuborishi mumkin.
Ammo observer aynan qaysi element o‘zgarganini bilishi kerak bo‘lsa changed IDlar ro‘yxati saqlanadi.
Bog‘liq tushunchalar
Behavioral pattern, Subject, Observer, Event, Publisher, Subscriber, Event bus, Publish-Subscribe, Reactive programming, Domain event