Observer(Design Pattern)
Observer tasarım deseni, birden fazla nesneyi, takip ettikleri başka bir nesnede gerçekleşen olaylarla ilgili bilgilendirmeyi sağlayan bir abonelik mekanizması oluşturmayı amaçlayan behavioral tasarım modelidir(design pattern).
- abone nesnelerin referanslarını saklayan bir array alanı, subscriber[].
- bu listeye abone eklemeyi veya çıkartmayı sağlayan bir kaç dışa açık (public) metot, +update()
Kullanacağım içerikler ağırlıklı olarak refactoring.guru ve evrenbal.com sitesinden alınmıştır.
Örnek Problem
Customer
(Müşteri) ve Store
(Dükkan) adında iki nesne tipiniz olduğunu düşünün. Müşteri belirli bir markanın yakın zamanda piyasaya sürülecek ürünü ile son derece ilgili olsun. Müşteri mağazayı her gün ziyaret ediyor ve ürünün durumunu kontrol ediyor. Ancak ürün hala yoldayken bu ziyaretler de boşu boşuna yapılmış oluyor.
Alternatif olarak mağaza her yeni ürün geldiğinde bütün müşterilerine (spam olarak kabul edilebilecek) on binlerce mail gönderebilir. Bu müşterilerin her gün mağazaya gelmesini engellese de bu ürünlerle ilgilenmeyen müşteriler için sinir bozucu olabilir.
Bu durumda ya müşteri, ürünün kullanılabilirliğini kontrol etmek için zaman harcıyor ya da mağaza, yanlış müşterilere bildirimde bulunarak kaynakları boşa harcıyor.
Çözüm
Bir nesnenin bir durumu ile ilgileniyorsak bu nesne bizim için ana bir öznedir. Bu öznemize durum değişikliğini başka nesnelere de haber vereceği için yayıncı olarak adlandırmak daha doğru olur. Bu nesnenin durumunu takip etmek isteyen diğer nesneler de bu nesnenin aboneleridir.
Observer deseni, yayıncının sınıfı içerisine bir abonelik mekanizması eklenmesini tavsiye eder, böylece diğer nesneler bu nesnede gerçekleşen olaylara abone olabilir ya da abonelikten çıkabilir. Bu her ne kadar karmaşık görülse de aslında gayet basit bir süreçtir. Gerçekte süreç şöyle iler; 1) abone nesnelerin referanslarını saklayan bir array alanı 2) bu listeye abone eklemeyi veya çıkartmayı sağlayan bir kaç dışa açık (public) metot.
Bu mekanizma ile birlikte herhangi önemli bir olay olduğuna yayıncı tüm abonelerin üzerinden geçerek bu nesnelere özel bildirim metotlarını çağırabilir.
Gerçek dünyada uygulamaların tek bir yayıncı sınıfında gerçekleşen olaylarla ilgilenen onlarca abone sınıfı olabilir. Bütün bunları yayıncının içinde doğrudan belirtip bir bağımlılık oluşturmak istemezsiniz, hatta çoğu zaman bu aboneleri önceden bilemeyebilirsiniz.
Bu nedenle tüm abonelerin, yayıncının kendileri ile iletişime geçebileceği ortak bir arayüzü paylaşmaları önemlidir. Bu arayüz, yayıncının bağlamla ilgili bilgileri aktarabileceği parametreleri de olan bir bildirim metodu tanımlamalıdır.
Gerçek Dünya Örneği
Bir gazete veya dergiye abone olursanız, bir sonraki sayının mevcut olup olmadığını kontrol etmek için artık mağazaya gitmenize gerek yoktur. Bunun yerine yayıncı, yeni sayıları yayınlandıktan hemen sonra veya hatta önceden doğrudan posta kutunuza gönderir.
Yayıncı, abonelerin bir listesini tutar ve hangi dergilerle ilgilendiklerini bilir. Aboneler, yayıncının kendilerine yeni dergi sayıları göndermesini durdurmak istediklerinde istedikleri zaman listeden ayrılabilirler.
Uygulanabilirlik
Bir nesnedeki değişikliğin başka nesneleri de değiştirmesi gereken ve bu nesnelerin önceden bilinmesi mümkün olmayan durumlarda Observer desenini kullanabilirsiniz.
Bu sorunla genelde kullanıcı arayüzleri ile çalışırken karşılaşırsınız. Örneğin bir buton sınıfı oluşturursunuz ve bu butona tıklandığında istemcinin belirleyeceği özel kodları tetikleyebilmesini istersiniz.
Observer deseni yayıncının olay bildirimlerini abonelere gönderebilmesini sağlayan bir abonelik arayüzü oluşturur. Düğmelerinize bir abonelik mekanizması ekleyerek istemcinin düğmeye istediği özel kod parçalarını abone edebilmesini sağlarsınız.
Uygulamanızdaki bazı nesnelerin başka bir nesneyi, belirli kullanımlar veya belirli bir süre için izlemesi gereken durumlarda bu deseni kullanabilirsiniz.
Abonelik listesi dinamiktir, böylece aboneler istedikleri zaman abone olur veya abonelikten çıkabilirler.