Tasarım desenleri ile ilgili daha önceki makalemde Behavioral tasarım kalıpları gurubunda yer alan Memento tasarım deseni ile giriş yapmıştık. Bu makalemde de yine Behavioral tasarım kalıpları gurubunda yer alan Observer tasarım deseni ile devam edeceğim.

Observer tasarım desenindeki amaç:

Tasarlanmış olan sistem içerisinde, değişimini izlemek istediğimiz bir değer için kullanılır.

UML Diagramına bir göz atalım:

 

Subject: Takip edilecek olan nesnemiz.
Observer: Abstract gözlemci sınıfımız. Soyutlamanın sebebi ise birden fazla gözlemci tarafından takip edilebilmesini sağlamak.
ConcreteObserver: Gerçek takip eden nesnemiz.

Basit bir örnek yaparak konuyu daha iyi pekiştirelim.

Örneğimizi bir e-ticaret sitesindeki kullanıcı üzerine düşünebiliriz. İstediğimiz bir ürünün stoğundaki bir değişim veya fiyatındaki bir değişimi gözlemlemek/takip etmek isteyebiliriz.

İlk başta Subject görevini üstlenecek olan yani takip edilecek nesnemiz olan Product sınıfımızı oluşturalım.

    /// <summary>
    /// Subject - Takip edilecek olan nesnemiz.
    /// </summary>
    class Product
    {
        // Gözlemleyicilerimizi tutacağımız listemiz.
        private List<Observer> _observers = new List<Observer>();

        public void Attach(Observer observer)
        {
            _observers.Add(observer);
        }

        public void Detach(Observer observer)
        {
            _observers.Remove(observer);
        }

        private void Notify()
        {
            // Herhangi bir değişiklik olduğunda gözlemleyicilerimizin Update metotunu tetikleterek istenilen aksiyonu gerçekleştirebiliriz. Örneğin: Kullanıcılara e-posta atmak gibi düşünebilirsiniz.
            _observers.ForEach(o => { o.Update(); });
        }

        public void ChangeStock()
        {
            ... stok değiştirilme işlemleri
            // Stok değiştirildiğinde gözlemcilerimize bildiriyoruz.
            this.Notify();
        }
    }

Şimdi Observer olan soyut sınıfımızı hazırlayalım ve ardından gerçek uygulayan sınıfımız olan (ConcreteObserver) CustomerObserver‘ı oluşturalım.

    /// <summary>
    /// Observer - Soyut sınıfımız.
    /// Soyutlamamızın nedeni ise birden fazla sınıf tarafındanda takip edilmesini sağlamak.
    /// </summary>
    abstract class Observer
    {
        // Herhangi bir değişimde gözlemleyiciler tarafından yapılması istenilen aksiyonlar.
        public abstract void Update();
    }

Observer soyut sınıfınıda hazırladık ve içerisinde değişimler karşılığında yaptırılmak istenilen aksiyonu yani Update metotunu tanımladık.

Şimdi CustomerObserver sınıfına bir göz atalım.

    /// <summary>
    /// ConcreteObserver - Gerçek takip eden nesnemiz.
    /// </summary>
    class CustomerObserver : Observer
    {
        public override void Update()
        {
            Console.WriteLine("Takip ettiğim ürünün stoğu değişti.");
            Console.ReadLine();
        }
    }

Değişim sonrasında ise gözlemleyecek olan sınıfımız CustomerObserver update işlemi sonrasında gerçekleştireceği olan Update aksiyonunu uyguladık. Siz burada business rule’larınıza göre istediğinizi yapabilirsiniz. Örneğin kullanıcı e-posta ile bilgilendirilmek istenebilir gibi.

Şimdi kullanımına bir göz atalım:

        static void Main(string[] args)
        {
            Product product = new Product();

            // İlgili gözlemleyicimizi product nesnemize ekliyoruz ki değişim sonrasında notify edebilelim.
            product.Attach(new CustomerObserver());

            // Ürün stoğunu değiştiriyoruz.
            product.ChangeStock();
        }

İşte bu kadar, Product nesnemize yani subject’imize eklenen her gözlemleyici, ürünün stoğu değişmesi sonrasında notify ile bilgilendirilecek. Biz örneğimiz gereği aksiyon olarak ekrana “Takip ettiğim ürünün stoğu değişti.” yazdırdık.

Uygulamayı çalıştırdığınızda böyle bir ekran göreceksiniz.

Observer tasarım desenini kısaca özetlediğimizde yayımcılar(Publishers) ve aboneler(Subscribers) modelinin uygulandığını düşünebiliriz. Bire-çok ilişkisi ile bağlı nesnelere, olayları iletmek olduğunu da diyebiliriz

Kullanım alanı olarak çok sık karşımıza çıkmaktadır aslında. MVC mimarisine baktığınızda:

 

Model üzerindeki bir değişikliği View’a notify ediliyor. Model burada view’a independent bir durumda.

Bununla ilgili msdn üzerinde güzel bir yazıyı sizinle paylaşmak istiyorum:

When a model changes, the model iterates through all registered observers and notifies them of the change. This approach is often called “publish-subscribe.” The model never requires specific information about any views.

Başka bir kullanım örneği daha vermek gerekirse de event-based programlamada event-delegate ilişkileri örnek gösterilebilir.

Umarım yeterli bilgi ve anlaşılabilir bir örnek olmuştur. Bir sonraki makalemde görüşmek dileğiyle.

 

Gökhan Gökalp

View Comments

  • Güzel açıklama olmuş. Belki Observer soyut sınıfı yerine arayüz tanımlamak daha uygun olabilir. Java'da benzer bir tasarım vardı, bu sebeple asıl (alt) observer sınıflar sadece ondan türemek zorunda kalıyordu.

Recent Posts

DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server

In the first part of this DevEx series, I tried to explain Platform Engineering and…

4 ay ago

DevEx Series 01: Creating Golden Paths with Backstage, Developer Self-Service Without Losing Control

As an architect involved in platform engineering and DevEx transformation within a large-scale organization for…

5 ay ago

Event-Driven Architecture’larda Conditional Claim-Check Pattern’ı ile Event Boyut Sınırlarının Üstesinden Gelmek

{:en}In today’s technological age, we typically build our application solutions on event-driven architecture in order…

1 yıl ago

Containerized Uygulamaların Supply Chain’ini Güvence Altına Alarak Güvenlik Risklerini Azaltma (Güvenlik Taraması, SBOM’lar, Artifact’lerin İmzalanması ve Doğrulanması) – Bölüm 1

{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…

2 yıl ago

Identity & Access Management İşlemlerini Azure AD B2C ile .NET Ortamında Gerçekleştirmek

{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…

2 yıl ago