Observer design patterni.
Bugungi maqolamiz
Observer design pattern haqida bo’ladi. Ko’pchilik dasturchilar o’zimiz bilmagan holda ko’p yillar davomida ushbu design patternni ishlatib kelganmiz. Micrososft Asp.Net WebForms, Microsoft Asp.Net MVC, Windows Application, GWT(Google Web Toolkit), Java Swing, ushbularni ishlatgan bo’lsangiz siz ham Observer design patternining qulayliklaridan foydalangansiz.
Maqola uch qismdan iborat bo’ladi. Birinchi qismda
GOF tomonidan berilgan ta’birni keltiramiz undan tashqari ba’zi foyda va kamchiliklarga ham e’tibor berib o’tamiz. Ikkinchi qismda aniq bir muammoni muhokama qilib, ushbu design pattern yordamida unga yechim topamiz. Uchinchi qismda esa implementatsiya qilamiz.
Birinchi qism. Observer design patterni qachon ishlatiladi? Biri boshqasidan taqozo qilgan, birga-ko’p usulida bog’langan obyektlardan iborat tizimda, agar obyekt o’z holatini o’zgartirsa unga buysunuvchi boshqa obyektlar ham o’z holatini avtomatik o’zgartishi lozim bo’lgan holatlarda ishlatiladi. Quyidagi rasmda ushbu holatga mos keluvchi diagramma berilgan.
Observer
obyekt doim Subject
obyektdan taqozo qiladi shu sabab doimo uni kuzatib turadi. Agar Subject
da biror o’zgarish bo’lsa darrov o’zidagi ma’lumotni yangilaydi. Bu jarayonga quyidagicha erishiladi. ConcreteSubject
da biror o’zgarish bo’lsa, u Notify()
metodni chaqiradi va unga buysunuvchi Observer
larga o’zgarish bo’lgani haqida habar beradi. Bir Subject
birdan ko’p kuzatuvchilarga ega bo’lishi mumkin. Buning uchun Attach()
va Detach()
metodlaridan foydalaniladi. Ushbu design patternda P2I prinsipi juda go’zallik bilan amalga oshirilgan. Ya’ni abstrakt darajada saqlanadigan biror bir Subject
unga bo’glanda Observer
ichida nima borligidan bexabar bo’ladi. U faqat Notify()
chaqirishni biladi holos. Undan Subject
ning o’zi abstarkt darajada joylashgani sabab undan meros olgan classlar Attach()
va Detach()
metodlarni ham meros oladi. Rasmda ko’rinib tuganidek, subject obyekti o’z ichida barcha observer obyektlarni saqlaydi. Open/Closed prinsipiga asosan turli yangi ConcreteSubject
larni qo’shib borishimiz mumkin. Yanada tushunarliroq bo’lishi uchun kodga qarashingiz so’rayman. Ikkinchi qism Muammo: Tassavur qiling, pochta xizmati orqali Qo’qondan Shovotga yuk jo’natildi. Yukning manzilga yetgunga qadar vaqtinchalik to’xtagan manzillari haqidagi ma’lumotlar ketma-ketligini ko’rsating. Yuk 2 hil statusga ega bo’lishi mumkin. «Ro’yhatdan o’tdi» va «Jo’natildi». Quyidagi rasmda ushbu jarayonning umumiy ko’rinishi berilgan.
Rasmdan ko’rinib turibdiki yuk Qo’qondan yo’lga chiqqan, Toshkent shahriga kelgan va ro’yhatdan o’tgan ma’lum vaqtdan so’ng yana jo’natilgan. Va Jizzahga yetib borguncha «Jo’natildi» statusi ostida bo’lgan. Maqsadimiz, har safar yuk o’z statusini o’zgartirganda bu haqida foydalanuvchini habardor qilish. Buning uchun Observer design patternidan foydalanamiz. Endi ushbu tizim uchun ishlatiladigan obyektlarni muhokama qilamiz va Oberver design patterndagi mos obyektlar bilan o’rin almashtiramiz. Subject
ga mos Yuk
classni bo’lishi aniq. Yuk
nom, manzil, va status kabi hususiyatga ega bo’lsin. Yuk
ning holat o’zgarishini kuzatuvchi Observer yaratamiz uning nomi YukReporter
bo’lsin. Demak:
Uchinchi qism. Diagramma berilgan classlarni birma-bir yozib chiqamiz. IObserver
interface.
//kuzatuvchi uchun interface public interface IObserver { void Update(); }
Subject
abstrakt classi.
//subject abstract classi public abstract class Subject { //kuzatuvchilarning ro'yhati private readonly List_observers; //kunstruktor protected Subject() { _observers = new List (); } //kuzatuvchini ro'yhatdan o'tqazish public void Attach(IObserver observer) { _observers.Add(observer); } //kuatuvchini ro'yhatdan chiqarish public void Detach(IObserver observer) { _observers.Remove(observer); } //obyektdagi o'zgarishlardan kuzatuvchini habardor qiladi public void Notify() { foreach (IObserver observer in _observers) { observer.Update(); } } }
Yuk
classi.
//konkret subject obyekt public class Yuk : Subject { public string Name { get; set; } public string Manzil { get; set; } private string _status; //faqat status o'zgarganda kuzatuvchiga habar ketadi public string Status { get { return _status; } set { _status = value; Notify(); } } }
Yuk
ni kuzatib boruvchi YukReporter
.
//konkret kuzatuvchi public class YukReporter : IObserver { //kuatilayotgan obyekt private readonly Yuk _yuk; public YukReporter(Yuk yuk) { _yuk = yuk; } //obyekt o'zgarish haqida habar kelgan, ekrandagi ma'lumotni yangilaydi public void Update() { if (_yuk != null) { Console.WriteLine("Yuk nomi: {0} -----------------------", _yuk.Name); Console.WriteLine("Manzil: {0} Status: {1}", _yuk.Manzil, _yuk.Status); } } }
Ushbu kodni ishga tushuruvchi
main
metod.
static void Main(string[] args) { //manzillar ro'yhati string[] manzillar = { "Qo'qon", "Toshkent", "Toshkent", "Jizzah", "Jizzah", "Qarshi", "Qarshi", "Shovot" }; //statuslar string[] statuslar = { "Jo'natildi", "Ro'yhatdan o'tdi", "Jo'natildi", "Ro'yhatdan o'tdi", "Jo'natildi", "Ro'yhatdan o'tdi", "Jo'natildi", "Ro'yhatdan o'tdi" }; Yuk yuk = new Yuk() { Name = "Iphone 5" }; //kuzatuvchi IObserver observer = new YukReporter(yuk); //kuzatuvchi ro'yhatdan o'tdi yuk.Attach(observer); //yuk yo'lga chiqdi for (int i = 0; iUshbu uslubning kamchiliklaridan biri, agar observer detach qilinmasa o'zaro bir-biriga bog'langan obyekt soni ko'payib ketishi mumkin natijada esa xotira bilan bo'gliq muammolar kelib chiqadi. Buning oldini olish uchun .Net Framework ning 4-versiyasidan boshlanga
Manba:IObserver
dan foydalanagan ma'qul. To'liq kod bilan ushbu link orqali tanishishingiz mumkin.
Algoritm
Observer design patterni.