Observer Pattern in .NET


After writing the article of Strategy pattern I thought that it would be useful to write a small article about the Observer pattern. This is a pattern I have been addicted to during my application designs. Specifically I prefer this pattern because it makes the objects very loosely coupled with each other. And in the .Net framework also used this pattern heavily.

When it comes in to the world of C#, the best example and implementation we can provide for the Observer pattern is the delegates with events.

Here let's go to a quick example:

I used representative names for the class(s) since we do not go for a real world scenario; I thought it would be easier this way…

PLEASE READ THE COMMENTS

using System;
using System.Threading;

namespace Observer_Pattern
{
    class CustomEventArgs: EventArgs
    {
        /* Your parameters to pass each observer comes here */
    }
 
    class Subject
    {
        /* This delegate holds the list of methods to be invoked when subject chnages */
        public delegate void subjectchnageddelegate(CustomEventArgs e);
       
/* This is an wrapper around the subjectchnageddelegate to avoid executing it externally
         * event gives publisher-subscriber model to the delegate
         */
        public event subjectchnageddelegate SubjectStatusChnaged;
 
        /* This is the method where subject is notifying to the oberservers */
        private void Notify()
        {
           
/* Interlocked is the best way to check whether event is null in a thread safe way            
             */
            Interlocked.CompareExchange(ref SubjectStatusChnaged, null, null);
 
            if (SubjectStatusChnaged != null)
            {
                /* Now we notify */
                SubjectStatusChnaged(new CustomEventArgs());
            }
        }

        /* In the sake of this article I add this method to here
         * Otherwise diffcult to demonstrate execution of Notify since there's no logic part implemetation
         */
        public void TempMethod()
        {
            /* The only thing this method does is executing the Notify */
            this.Notify();
        }
    }
 
    /// <summary>
    /// One of the Observers
    /// </summary>
    class Observer1
    {
        public Observer1(Subject s)
        {
            /* Add method to delegate */

            s.SubjectStatusChnaged += new Subject.subjectchnageddelegate(s_SubjectStatusChnaged);
        }

        private void s_SubjectStatusChnaged(CustomEventArgs e)
        {
            Console.WriteLine("Observer1 notified");
        }
    }

    /// <summary>
    /// Another observer
    /// </summary>
    class Observer2
    {
        public Observer2(Subject s)
        {
            /* Add method to delegate */
            s.SubjectStatusChnaged += s_SubjectStatusChnaged; /* This is a c-sharp language shortcut to add method to delegate */
        }
 
        private void s_SubjectStatusChnaged(CustomEventArgs e)
        {
            Console.WriteLine("Observer2 notified");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            /* This is our subject */
            Subject s = new Subject();

            /* 1st Observer */
            Observer1 o1 = new Observer1(s);
            /* 2nd Observer*/
            Observer2 o2 = new Observer2(s);

            /* Calling the Notify manually - For the sake of explanation of this article :) */
            s.TempMethod();

            Console.ReadLine();
        }
    }
}

Here we can see the output

ObsPtrn1.gif

Here you may notice that I have used a delegate as I said in the beginning of the article. This is where we can see the power of delegates in C#. So what about Java, can't we implement the observer pattern in Java?

Why not!! Yes, you can

When it's Java, this is slightly different, since we don't have delegates (function pointers in C++) or any other similar implementation in Java. But we can achieve the same functionality like this:

//Subject class

package observer.in.java;

import java.util.ArrayList;
import java.util.List;

public class Subject {    
       List<Observer>
l = new ArrayList<Observer>(2);

    public void RegisterObserver(Observer o)
    {
       
if (o != null)
           
l.add(o);
    }

    public void UnRegisterObserver(Observer o)
    {
       
if (o != null)
           
l.remove(o);
    }

    private void Notify()
    {
       
for (int i = 0; i < l.size(); i++)
        {
           
l.get(i).Method();
        }
    }

    public void TempMethod()
    {
       
this.Notify();
    }
}

//Observers base class

package observer.in.java;

public abstract class Observer {
   
/* Implement the Equals and GetHashCode here!! */
    public abstract void Method();
}

//Observer1 Implementation

package observer.in.java;

public class Observer1 extends Observer {
        
public void Method()
     {
         System.
out.println("Observer 1 notified");
     }
}

//Observer2 Implementation

package observer.in.java;

public class Observer2 extends Observer {
        
public void Method()
     {
         System.
out.println("Observer 2 notified");
     }
}

//Program class
package observer.in.java;
 
public class Program {

       public static void main(String[] args) {
        
/* Create the subject */
        Subject s = new Subject();

        /* Create Observers */
        Observer1 o1 = new Observer1();
        Observer2 o2 =
new Observer2();

        /* Register all observers */
        s.RegisterObserver(o1);
        s.RegisterObserver(o2);
 
        /* Notify manually - for this article purpose only!! */
        s.TempMethod();
       }
}

Here we see the same output:

ObsPtrn2.gif

That's about the Observer pattern. Hope you can map this with your real world solutions.

Good Luck

 


Similar Articles