Introduction

The Observer Pattern is a mechanism for drastically reducing coupling between interacting classes. The observer pattern should be used whenever one or more objects (observers) must track changes in the subject. The subject maintains a list of its observers. Each observer must register as an observer of the subject. When the subject changes, it notifies all its observers that it has changed. The observers are then responsible for querying the subject for any additional information they need about the changes to the subject.

In this article we will examine how to implement observer pattern using C# and also the built in support for observer pattern in .NET framework using events and delegates.

Observer Pattern

Observer defines a one to many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The Observer pattern has one subject and potentially many observers. Observers register with the subject, which notifies the observers when events occur.

Participants

Subject

Keeps track of its observers

Provides an interface for attaching and detaching Observer objects

Observer

Defines an interface for update notification

ConcreteSubject

The object being observed

Stores state of interest to ConcreteObserver objects

Sends a notification to its observers when its state changes

ConcreteObserver

The observing object

Stores state that should stay consistent with the subject's

Implements the Observer update interface to keep its state consistent with the subject's

Implementation Strategy

Bangalore Airlines is a regional airline that operates 10 scheduled flights per day. The company anticipates rapid future growth. Currently company’s telephone operators handle all the reservations. To support the increased number of customers, company plans to appoint two travel agents, Southern Travels and National Travels. Travel agents would be notified, whenever National Airlines add new flights. If this model works fine, they will be working with more Travel Agents.

We need to design a system which would automatically notify the travel agents about the new flights added by Bangalore Airlines. Also this design should accommodate any new travel agents in the system with minimum modifications to the existing system.

This is the ideal scenario for implementing Observer pattern. This pattern is applicable when

When a change to one object requires changing others, and you don't know how many objects need to be changed.

When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.

Let’s start our design by identifying participants for the pattern.

Subject

We need to identify a subject which would keep track of its observers and provides an interface for attaching and detaching observer objects. The subject is an abstract class which has methods for adding, removing observers and notify observers about changes to concrete subject.

ConcreteSubject

This is the object being observed. You need to observe changes to Bangalore Airlines in the form of adding new flights. Whenever changes happen to Bangalore Airlines, it would notify observers about this change.

When Bangalore Airlines associate with more travel agents, all it has to do is just create the new observer class and attach in the client code. Let’s have a look at the benefits gained by implementing this pattern for the system

1. Abstract coupling between Subject and Observer.

All a subject knows is that it has a list of observers, each conforming to the simple interface of the abstract Observer class. The subject doesn't know the concrete class of any observer. Thus the coupling between subjects and observers is abstract and minimal.

2. Support for broadcast communication.

Unlike an ordinary request, the notification that a subject sends needn't specify its receiver. The notification is broadcast automatically to all interested objects that subscribed to it. The subject doesn't care how many interested objects exist; its only responsibility is to notify its observers. This gives you the freedom to add and remove observers at any time. It's up to the observer to handle or ignore a notification.

References

Conclusion

Implementation of Observer in .NET is simple and straightforward. However, as the number of observers increases, it would be difficult to follow what happens when a notification happens. As a result code can be very difficult to debug as we need to search through the code for the observers.

There is no need for Subject, Subject Helper and observer types for implementing Observer in .net. Observer can be very easily implemented by using events and delegates in .NET.

Comments and Discussions

A BangaloreAirlines object can be created only once and all the Travels agents have been added to this object. So the information about the route cannot be given in the constructor. What happens when a new route has to be added? Do we create another BangaloreAirlines object and again add Travel agents to it??

One limitation in the .net handling of events is that an event subscriber will be kept alive as long as it holds a event subscription, even if the event publisher is the only surviving reference. Any objects which the event subscriber is supposed to update will in turn be kept alive, with the effect that a failure to dispose an event subscriber can generate massive memory leaks.

What would be the performance implications of implementing the pattern with a weak reference to an event subscriber object which in turn held a delegate pointing to the 'real' object? The real object would have to maintain a strong reference to the subscriber object to prevent its accidental unsubscription (a requirement not normally applicable to .net events) but both the real object and the subscription object would become eligible for garbage collection when the last reference other than the subscription itself vanished.

Since .net (as of 2.0) does not unfortunately support a generic version of WeakReference, invoking a subscription would require a typecast which would impose some overhead, but potential serious memory leaks would be avoided.

I think you should have this remark about the second implementation.
In the first one you have a quite tight coupling because of the interface you request for the observer to implement.
I think you are misleading in your article.
And that is mostly because you present the "benefits" for your first example, while most of them are for the second example.

Plus, I truly see no difference between you article and the one from Microsoft, except maybe different names and poorer English.

In the first part of the article i was trying to emphasize on the advantages of using the pattern. Coupling between subjects and observers is abstract when compared to the normal way of handling these kinds situations.(Where classes are tightly coupled).

Again i never said the coupling between subjects and observers is 100% abstract but the coupling between subjects and observers is abstract and minimal.

It would be great if you could help me to improve the English by editing this article..

Good response to the question of English language, this is a professional platform and we must watch the technical result instead of taunting on bad English. Yes the starting of article is copied from http://www.dofactory.com/Patterns/PatternObserver.aspx[^], but still it has a great different real life example. So no need to taunt.

But the subject class needs to maintain the repository of observer objects. Isn't it an overhead as compared to the event and delegates?

Moreover, while developing this mechanism, we need to know the nature of all observer types and define an interface for them to maintain the repository of observers in subject, like List and all observer types should implement the IObserver.

what if later on any registered Customer also needs to get configured against flight additions etc.

Whereas if you use event and delegates then any kind of object can be observer by just defining handler of that delegate type.

I thought the same thing until I tried my hand at remoting. In remoting (in any version of .NET 1.1 and above) if you try to use events across the wire you get security exceptions. You can turn these off but they are really there for your safety. However, the observer pattern still works flawlessly.