Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C#

Understanding and Implementing Observer Pattern in C#

Rate me:
Please Sign up or sign in to vote.
4.93/5 (21 votes)
10 Feb 2012CPOL3 min read 94.1K   1.5K   41   16
Understanding and Implementing Observer Pattern in C#

Introduction

This article presents the basics of Observer Pattern, when to use it and how to implement it in C#.

Background

Many a times, we need one part of our application updated with the status of some other part of the application. One way to do this is to have the receiver part repeatedly check the sender for updates, but this approach has two main problems. First, it takes up a lot of CPU time to check the new status and second, depending on the interval we are checking for change we might not get the updates "immediately".

This problem has one easy solution i.e. Observer Pattern. I know many guys will shoot me in the neck on reading this article because this perhaps is going to be 100th article on CodeProject alone but still I think it is worth sharing it, as it could be useful for the beginners and also the valuable comments I get on the article will let me learn more.

Here is the Class diagram for the Observer pattern (Reference: GoF Design Patterns)

Image 1

Using the Code

Let us now discuss all the classes one by one:

  • Subject: This class keeps a track of all the observers and provides the facility to add or remove the observers. Also it is the class that is responsible for updating the observers when any change occurs. In our solution, we have ASubject implemented for the same purpose.
  • ConcreteSubject: This class is the real class that implements the Subject. This class is the entity whose change will affect other objects. We have DummyProject class implemented for the same.
  • Observer: This represents an interface that defines the method that should be called whenever there is change. We have implemented this as IObserver.
  • ConcreteObserver: This is the class which needs to keep itself updated with the change. This class just needs to implement the Observer and register itself with the ConcreteSubject and it is all set to receive the updates. We have Shop class in our application serving the same purpose.

So let me just have the same diagram I've shown above for my implementation here:

Image 2

Before we go ahead and see the code, there is one more thing I want to say here. In .NET, we have delegates which are actually a very good example of Observer pattern. So actually we don't need to implement the pattern completely in C# as we can use the delegates for the same functionality, but we have done it here for understanding the pattern. Also, we have implemented the delegate's way of having an observer pattern working too. So let's now look at the code.

The Subject: ASubject

C#
abstract class ASubject
{
    //This is the one way we can implement it, lets call it WAY_1
    ArrayList list = new ArrayList();

    //This is another way we can implement observer, lets call it WAY_2
    public delegate void StatusUpdate(float price);
    public event StatusUpdate OnStatusUpdate = null;

    public void Attach(Shop product)
    {
        //For way 1 lets assign attach the observers with subjects
        list.Add(product);
    }
    public void Detach(Shop product)
    {
        //For way 1 lets assign detach the observers with subjects
        list.Remove(product);
    }

    public void Attach2(Shop product)
    {
        //For way 2 lets assign attach the observers with subjects
        OnStatusUpdate += new StatusUpdate(product.Update);
    }
    public void Detach2(Shop product)
    {
        //For way 2 lets assign detach the observers with subjects
        OnStatusUpdate -= new StatusUpdate(product.Update);
    }

    public void Notify(float price)
    {
        //For way 1 lets notify the observers with change
        foreach (Shop p in list)
        {
            p.Update(price);
        }

        //For way 2 lets notify the observers with change
        if (OnStatusUpdate != null)
        {
            OnStatusUpdate(price);
        }
    }
}

The ConcreteSubject: DummyProduct

C#
class DummyProduct : ASubject
{
    public void ChangePrice(float price)
    {
        Notify(price);
    }
}

The Observer: IObserver

C#
interface IObserver
{
    void Update(float price);
}

The ConcreteObserver: Shop

C#
class Shop : IObserver
{
    //Name if the product
    string name;
    float price = 0.0f; //default

    public Shop(string name)
    {
        this.name = name;
    }
    #region IObserver Members

    public void Update(float price)
    {
        this.price = price;

        //Lets print on console just to test the working
        Console.WriteLine(@"Price at {0} is now {1}", name, price);
    }

    #endregion
}

Testing the Code

C#
static void Main(string[] args)
{
    DummyProduct product = new DummyProduct();

    // We have four shops wanting to keep updated price set by product owner
    Shop shop1 = new Shop("Shop 1");
    Shop shop2 = new Shop("Shop 2");

    Shop shop3 = new Shop("Shop 3");
    Shop shop4 = new Shop("Shop 4");

    //Lets use WAY_1 for first two shops
    product.Attach(shop1);
    product.Attach(shop2);

    //Lets use WAY_2 for other two shops
    product.Attach2(shop3);
    product.Attach2(shop4);

    //Now lets try changing the products price, this should update the shops automatically
    product.ChangePrice(23.0f);

    //Now shop2 and shop 4 are not interested in new prices so they unsubscribe
    product.Detach(shop2);
    product.Detach2(shop4);

    //Now lets try changing the products price again
    product.ChangePrice(26.0f);

    Console.Read();
}

Points of Interest

The heart of Windows Forms programming and MPF Applications is the Observer Pattern. Since the event driven mechanism can only be facilitated by implementing the Observer pattern, I wrote a very basic and perhaps "not-so-useful-to-others-who-know-stuff" article, but I did enjoy learning and writing it. Now the next step for me is to implement the same in C++ (with pointers, vectors, iterators and other good stuff).

History

  • 10 February, 2012: Simple and rudimentary implementation of Observer pattern in C#

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India

I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.

  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4

If you like my articles, please visit my website for more: www.rahulrajatsingh.com[^]

  • Microsoft MVP 2015

Comments and Discussions

 
GeneralMy vote of 2 Pin
johannesnestler9-Apr-14 4:55
johannesnestler9-Apr-14 4:55 
GeneralRe: My vote of 2 Pin
Rahul Rajat Singh9-Apr-14 18:42
professionalRahul Rajat Singh9-Apr-14 18:42 
GeneralMy vote of 5 Pin
Member 99569873-Apr-14 10:56
Member 99569873-Apr-14 10:56 
QuestionUnderstanding and Implementing Observer Pattern in C# Pin
rajacsharp527-Dec-13 5:08
rajacsharp527-Dec-13 5:08 
QuestionThe Update 2 and attach 2 are slower than traditional approach Pin
Member 22379787-Oct-13 7:07
Member 22379787-Oct-13 7:07 
GeneralMy vote of 5 Pin
dangkyally19-Sep-13 23:42
dangkyally19-Sep-13 23:42 
GeneralMy vote of 5 Pin
Member 99774474-May-13 9:55
Member 99774474-May-13 9:55 
GeneralMy vote of 5 Pin
chaz-chance9-Apr-13 0:15
chaz-chance9-Apr-13 0:15 
GeneralMy vote of 5 Pin
hernaldo.gonzalez21-Feb-13 6:50
hernaldo.gonzalez21-Feb-13 6:50 
GeneralMy vote of 3 Pin
karthik cad/cam21-Nov-12 20:14
karthik cad/cam21-Nov-12 20:14 
GeneralRe: My vote of 3 Pin
chaz-chance9-Apr-13 0:19
chaz-chance9-Apr-13 0:19 
GeneralMy vote of 1 Pin
FerretallicA26-Mar-12 13:31
FerretallicA26-Mar-12 13:31 
Questionthanks! Pin
bbls198319-Feb-12 20:43
bbls198319-Feb-12 20:43 
Perfect Articles
no

GeneralMy vote of 1 Pin
SledgeHammer0111-Feb-12 7:36
SledgeHammer0111-Feb-12 7:36 
GeneralRe: My vote of 1 Pin
chaz-chance9-Apr-13 0:20
chaz-chance9-Apr-13 0:20 
GeneralMy vote of 5 Pin
Quentin in SA10-Feb-12 20:49
Quentin in SA10-Feb-12 20:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.