Observer Design Pattern in C#

Observer Design Pattern in C# with Examples

In this article, I am going to discuss the Observer Design Pattern in C# with examples. Please read our previous article where we discussed the Iterator Design Pattern in C#. The Observer Design Pattern falls under the category of Behavioral Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is the Observer Design Pattern?
  2. Example to understand the Observer Design Pattern in C#.
  3. When to use the Observer Design Pattern in C#?
What is the Observer Design Pattern?

According to GoF, the Observer design Pattern should “Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically”.

The Observer Design Pattern is a Software Design Pattern in which an object (called as Subject) maintains a list of its dependents (called as Observers) and notifies them automatically whenever any state changes by calling one of their methods.

The Observer Design Pattern defines a one-to-many dependency between objects so that when one objects state changes, all its dependents are notified and updated automatically.

The Other names of this pattern are Producer/Consumer, Publish/Subscribe.

How does the Observer Design Pattern work?

The observer design pattern is having two main components. They are as follows

  1. Subject. They are the publishers. When a change occurs to a subject it should notify all of its subscribers.
  2. Observers. They are the subscribers. They simply listen to the changes in the subjects.

Another name of the Observer is the Listener. Please have a look at the following diagram.

Observer Design Pattern in C#

As shown in the above image, we can define the Subject as an object which maintains a list of observers. The Subject having methods to Register and unregister the observers. As you can there are three observers are registered within the subject. If any new observer wants to register then he/she needs to call the Register method of the Subject. Again if any observer wants to unregister then he/she simply needs to call the unregister method of the subject.

The subject has some state. Whenever there are some changes occurred in the state, then the subject will notify all the observers which are registered in the subject by calling one of the observer methods.

Once the observer gets the notification from the subject, it will call one of the methods of the subject to get the change state data.

A real-time example of the Observer Design Pattern:

Let us understand the Observer Design Pattern with an example. Please have a look at the following diagram. Here, we are taking an example of Amazon.

Real-time example of Observer Design Pattern in C#

As you can see in the above image, three users come to the Amazon site for buying a Mobile Phone. Unfortunately, at that time the Mobile phone is out of stock i.e. the mobile is in Not Available state. But the above three users want to buy that particular mobile. In the Amazon site, there is an option called to notify me when the product is available. What the above three users do is, they registered with the above option, so that when the product is available, the Amazon site will send a notification to them.

After a few days, the Product is available, and so the status is changed from Out Of Stock to available. So, what Amazon will do is send notifications to all the users who are registered. As we already discussed the Observer Design Pattern has two main components i.e. the Subject and the Observer. In our examples, the Mobile is the Subject and three users (i.e. User1, User2, and User3) are the Observers. For better understanding please have a look at the following image.

Observer Design Pattern Realtime Example in C#

As per the Observer Design Pattern, the Observers need to be registered to the Subject. In our case, the three users are registered to the notification option of the Subject. When the state changes i.e. Out of Stock to Available the Subject will send a notification to all the subscribers.

Let us see the step by step implementation of the Observer Design Pattern in C#.

Step1: Creating the Subject interface

Create a class file with the name ISubject.cs and then copy and paste the following code in it. The Subject knows its Observers and provides an interface for adding or removing any number of Observer objects.

namespace ObserverDesignPattern
{
    public interface ISubject
    {
         void RegisterObserver(IObserver observer);
         void RemoveObserver(IObserver observer);
         void NotifyObservers();
    }
}
Step2: Creating Concrete Subject

Create a class file with the name Subject.cs and then copy and paste the following code in it. The ConcreteSubject objects store the states of interest to the Observers and also responsible for sending the notification to its observers when its state changes.

using System;
using System.Collections.Generic;

namespace ObserverDesignPattern
{
    public class Subject : ISubject
    {
        private List<IObserver> observers = new List<IObserver>();
        private string ProductName { get; set; }
        private int ProductPrice { get; set; }
        private string Availability { get; set; }

        public Subject(string productName, int productPrice, string availability)
        {
            ProductName = productName;
            ProductPrice = productPrice;
            Availability = availability;
        }
        
        public string getAvailability()
        {
            return Availability;
        }

        public void setAvailability(string availability)
        {
            this.Availability = availability;
            Console.WriteLine("Availability changed from Out of Stock to Available.");
            NotifyObservers();
        }

        public void RegisterObserver(IObserver observer)
        {
            Console.WriteLine("Observer Added : " + ((Observer)observer).UserName );
            observers.Add(observer);
        }

        public void AddObservers(IObserver observer)
        {
            observers.Add(observer);
        }

        public void RemoveObserver(IObserver observer)
        {
            observers.Remove(observer);
        }

        public void NotifyObservers()
        {
            Console.WriteLine("Product Name :"
                            + ProductName + ", product Price : "
                            + ProductPrice + " is Now available. So notifying all Registered users ");

            Console.WriteLine();
            foreach (IObserver observer in observers)
            {
                observer.update(Availability);
            }
        }
    }
}
Step3: Creating Observer Interface:

Create a class file with the name IObserver.cs and then copy and paste the following code in it. The Observer defines an updating interface for objects that should be notified of changes in a Subject.

namespace ObserverDesignPattern
{
    public interface IObserver
    {
        void update(string availability);
    }
}
Step4: Creating Concrete Observer

Create a class file with the name Observer.cs and then copy and paste the following code in it. It maintains a reference to a ConcreteSubject object and implements the Observer interface to keep its state consistent with that of the Subjects.

using System;
namespace ObserverDesignPattern
{
    public class Observer : IObserver
    {
        public string UserName { get; set; }

        public Observer(string userName, ISubject subject)
        {
            UserName = userName;
            subject.RegisterObserver(this);
        }
        
        public void update(string availabiliy)
        {
            Console.WriteLine("Hello " + UserName + ", Product is now " + availabiliy + " on Amazon");
        }
    }
}

In order to test everything is working as expected, let modify the Main method as shown below.

using System;
namespace ObserverDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create a Product with Out Of Stock Status
            Subject RedMI = new Subject("Red MI Mobile", 10000, "Out Of Stock");

            //User Anurag will be created and user1 object will be registered to the subject
            Observer user1 = new Observer("Anurag", RedMI);

            //User Pranaya will be created and user1 object will be registered to the subject
            Observer user2 = new Observer("Pranaya", RedMI);

            //User Priyanka will be created and user3 object will be registered to the subject
            Observer user3 = new Observer("Priyanka", RedMI);
            
            Console.WriteLine("Red MI Mobile current state : " + RedMI.getAvailability());
            Console.WriteLine();

            // Now product is available
            RedMI.setAvailability("Available");

            Console.Read();
        }
    }
}

Output:

Observer Design Pattern in C#

Real-Time Examples:

The Company needs to notify all its shareholders for any decision they make. Here, Company is the Subject and Shareholders are Observers. Any change in the policy of the company and the company need to notify all its Shareholders or you can say, Observers. This is a simple real-world explanation of the Observer Design Pattern.

A Typical use Case:

A mailing list where every time an event happens (i.e. a new product, a gathering, etc.) a message needs to send to the users who subscribed to the list.

In the next article, I am going to discuss the Chain of Responsibility Design Pattern in C# with some examples. Here, in this article, I try to explain Observer Design Pattern in C# step by step with an example. I hope you understood the need and use of the Observer Design Pattern in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *