Observer Pattern
In this article, we will have a look at the observer pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state or data changes, usually by calling one of the method of observers (From Wikipedia).
In simpler words, the Observer pattern defines,
- Subject (provider) that is responsible for monitoring and updating some sort of data and sending the notification to the observers
- Observer that receives notification from Subject (provider).
- Low level of loose coupling between Subject and Observers by defining Subject and Observers in such a way that none of them have any explicit knowledge of each other but Subject maintains a list of Observers.
- Subject (provider) provides Observers a method to subscribe (attach) and unsubscribe (detach) themselves.
- A One-To-Many relationship between Subject (provider) and Observer which means a subject can have multiple dependents (observers) who want to get notified when change happens in the subject state, for example, a library named “TemperatureCalculatorLibrary” (Subject) which computes temperature can have many dependents applications (Observers) who need the updated temperature data for displaying or further calculation or predictions.
- A solution for push-based notification where Subject provides Observers the updated data or notifies all the observers by calling one of their methods whenever there is any change happens to the subject’s state or data - there is no way that observers themselves update or get the data from a subject.
Now, let’s have a look at the general implementation to understand the Observer pattern in a more detailed way.
Define an interface named “IObserver” that contains a property to store a name of the observer object and differentiate two objects from each other. A method named “UpdateObserver” that is being called by the Subject to notify the observer object and this is the method which almost every observer class would have.
- public interface IObserver
- {
- string ObserverName { get; set; }
- void UpdateObserver();
- }
- public class Subject
- {
- private readonly List<IObserver> _observers = new List<IObserver>();
- public string SubjectName { get; set; }
- public Subject(string subjectName)
- {
- SubjectName = subjectName;
- SubjectState = "Created";
- Console.WriteLine("Instantiated named Subject {0}", SubjectName);
- }
- public string SubjectState { get; set; }
- public void Subscribe(IObserver observer)
- {
- _observers.Add(observer);
- Console.WriteLine("Observer named {0} is now added to the {1}'s observers list and will receive notification when change happens to the subject {1} state", observer.ObserverName, SubjectName);
- }
- public void Unsubscribe(IObserver observer)
- {
- _observers.Remove(observer);
- Console.WriteLine("Observer named {0} is removed from the {1}'s observers list and will no longer receive notification when change happens to the subject {1} state", observer.ObserverName, SubjectName);
- }
- public void NotifyObservers()
- {
- foreach (IObserver observer in _observers)
- {
- observer.UpdateObserver();
- }
- }
- public void ModifySubjectStateOrData(string subjectStateOrData)
- {
- Console.WriteLine("{0} state changed from {1} to {2}", SubjectName, SubjectState, subjectStateOrData);
- SubjectState = subjectStateOrData;
- NotifyObservers();
- }
- }
- public class Observer : IObserver
- private Subject _subject;
- public Observer(string observerName)
- {
- ObserverName = observerName;
- }
- public string ObserverName { get; set; }
- public void Subscribe(Subject subject)
- {
- _subject = subject;
- subject.Subscribe(this);
- }
- public void Unsubscribe()
- {
- _subject.Unsubscribe(this);
- }
- public void UpdateObserver()
- {
- Console.WriteLine("{0} received the notification", ObserverName);
- }
- static void Main(string[] args)
- {
- Subject S1 = new Subject("S1");
- Observer O1 = new Observer("O1");
- Observer O2 = new Observer("O2");
- O1.Subscribe(S1);
- O2.Subscribe(S1);
- S1.ModifySubjectStateOrData("Approved");
- Console.WriteLine();
- O2.Unsubscribe();
- S1.ModifySubjectStateOrData("Implemented");
- Console.ReadLine();
- }

As we look at the above implementation we can see that Observer and Subject know about each other, which means to some extent they are coupled (not completely loosely coupled). To overcome this problem, .NET Framework provides a generic System.IObservable<T> and System.IObserver<T> interfaces which can be implemented by Subject and Observer to apply Observer pattern.
As mentioned earlier, the observer design pattern is suitable for distributed push-based notifications and requires
- · A provider to send notifications to observers.
- · An observer that receives notifications from a provider.
Implement a Provider using a generic System.IObservable<T> interface
Define a provider class that implements the System.IObservable<T> interface where T is the type of data that the provider sends to an observer.
- The Provider class implements the single method “Subscribe” which provides an ability to an observer to register themselves with the Subject (provider). The “Subscribe” method stores a reference to the observer in a collection object, such as a List<T> object and returns a reference to an IDisposable interface that enables observers to unsubscribe (that is, to stop receiving notifications).
- The provider class implements a method that is responsible for notifying the observers by calling any one of the Observer method IObserver<T>.OnNext, IObserver<T>.OnError, and IObserver<T>.OnCompleted implemented.
Implement an Observer using generic System.IObserver<T> interface
Define the observer class that implements the System.IObservable<T> interface where T is the type of data that observer received from the provider,
- Defines a Subscribe method that calls the provider's Subscribe method and passes a reference of Observer instance
- Define a private variable that will hold the IDisposable implementation returned by the provider's IObservable<T>.Subscribe method
- Defines an Unsubscribe method that calls the Dispose method on the IDisposable object
- Provide implementations of the three methods defined by the IObserver<T> interface: IObserver<T>.OnNext, IObserver<T>.OnError, and IObserver<T>.OnCompleted.
Points to Remember
- The provider and observer may both try to remove the same member from the Observers list so both the Subscribe and Dispose of methods should be thread-safe.
- We should avoid an attempt to unregister in the IObservable<T>.Subscribe method because it may result in a null reference.
- Although it is possible to attach an observer to multiple providers, the recommended pattern is to attach an IObserver<T> instance to only one IObservable<T> instance.
- The observer should not throw exceptions from its interface implementations, such as OnNext or OnError.
Problem Statement
Suppose we have a video player which is responsible for playing video and keeping live video status, for example, how much time has already elapsed, how much video time is remaining, what percentage of the video is completed. Now, whenever video time elapsed changes by 10 minutes or video completed percentage exceeds 10 percent, all the observer GUI platforms must be notified so that respective GUIs can display current video live status.
The following example contains the complete source code for defining an IObservable<T> implementation for a Video Player monitoring application. It includes the VideoStatus structure, which is the data sent to observers, and the VideoStatusPercentageMonitor, VideoStatusMonitor, VideoStatusTimeMonitor - which are the IObserver<T> implementation.
Let’s have a look at the IObservable<T> implementation class named “VideoPlayer” – this class defines three methods to Start, Pause and Stop Video. A method named “GetVideoStatus” executing in a separate thread is initiated to update the current state in the data structure object i.e., VideoStatus,


Clerson VincentPosted Jul 9, 2019, 11:15 AM
I have some problems with the second exercise code. 1- You didn't put the VideoStatus class. public class VideoStatus { public int TimeRemaining { get; set; } public int TimeElapsed { get; set; } public double VideoCompletedPercentage { get; set; } public VideoStatusCode Status { get; set; } } 2- You didn't put VideoStatusCode ( Isuposed it's an enum) public enum VideoStatusCode { Running, Paused, Stopped } 3- And you didn't put the definition of the object "lockObject". Unfortunately I couldn't solve this error...
Farhan AhmedPosted Jul 24, 2018, 12:45 AM
Nice explanation