![]() |
Development Lifecycle »
Design and Architecture »
Patterns and Practices
Intermediate
License: The Code Project Open License (CPOL)
Observer Pattern in .NETBy Sunil Kumar K.SA mechanism for drastically reducing coupling between interacting classes |
C#, VB.NET 1.0, Win2K, WinXP, Win2003, ASP.NET, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
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 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.
Subject
Observer
ConcreteSubject
ConcreteObserver
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
Let’s start our design by identifying participants for the pattern.
SubjectWe 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.
public abstract class Subject
{
private ArrayList observers=new ArrayList();
public void AddObservers(Observer observer)
{
observers.Add(observer);
}
public void RemoveObserver(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
// Notify the observers by looping through
// all the registered observers.
foreach(Observer observer in observers)
{
observer.UpdateBangaloreAirlinesRout(this);
}
}
}
ConcreteSubjectThis is the object being observed. You need to observe changes to Bangalore Airlines in the form of adding new flights. Whenever changes happen to
public class BangaloreAirlines: Subject
{ public string TravelRout;
public double TravelFare;
public BangaloreAirlines(String RoutId, double Fare)
{
this.TravelRout=RoutId;
this.TravelFare=Fare;
}
public void AddNewRout()
{
Notify();
}
}
ObserverDefines an interface for Update notification.
Defines an interface for Update notification.
public interface Observer
{
void UpdateBangaloreAirlinesRout(object Traveller);
}
ConcreteObserversThese are the observing objects. Any changes to the concrete subject( Bangalore Airlines) should be reflected in the National Travels and Southern Travels.
public class NationalTravels:Observer
{
public void UpdateBangaloreAirlinesRout(object Traveller)
{
if( Traveller is BangaloreAirlines)
{
AddRoutforBangaloreAirlines(
(BangaloreAirlines)Traveller);
}
}
private void AddRoutforBangaloreAirlines(BangaloreAirlines
traveller)
{
//Code for adding the new rout to NationalTravel's
//Travel database.
Console.WriteLine("new rout No. " +
traveller.TravelRout + " Added Sucessfully to
National Travel's Database");
}
}
public class SouthernTravels : Observer
{
public void UpdateBangaloreAirlinesRout(object Traveller)
{
if( Traveller is BangaloreAirlines)
{
AddRoutforBangaloreAirlines
((BangaloreAirlines)Traveller);
}
}
private void AddRoutforBangaloreAirlines(BangaloreAirlines
traveller)
{
//Code for adding the new rout to Southern Travel's
//Travel database.
Console.WriteLine("new rout No. " +
traveller.TravelRout + " Added Sucessfully to
SothernTravel's Database");
}
}
Now we need to implement a client for testing this application. It’s where you will attach the observers to the concrete subject.
class Client
{
[STAThread]
static void Main(string[] args)
{
BangaloreAirlines AirLines= new BangaloreAirlines("EC
2012",2230);
NationalTravels National=new NationalTravels();
SouthernTravels Southern=new SouthernTravels();
//Attach observers
AirLines.AddObservers(National);
AirLines.AddObservers(Southern);
AirLines.AddNewRout();
Console.ReadLine();
}
}
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
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.
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.
Just that each observer implements the update interface
BangaloreAirlines class should expose an event UpdateEvent
public class BangaloreAirlines
{
public delegate void UpdateHandler(object sender);
public event UpdateHandler UpdateEvent;
public string TravelRout;
public double TravelFare;
public BangaloreAirlines(String RoutId, double Fare)
{
this.TravelRout=RoutId;
this.TravelFare=Fare;
}
public void AddNewRout()
{
Notify();
}
private void Notify()
{
if (UpdateEvent!=null)
UpdateEvent(this);
}
}
The observers must create a specific delegate instance and register this delegate with the subject’s event.
public class NationalTravels
{
public void UpdateBangaloreAirlinesRout(object Traveller)
{
if( Traveller is BangaloreAirlines)
{
AddRoutforBangaloreAirlines
((BangaloreAirlines)Traveller);
}
}
private void AddRoutforBangaloreAirlines
(BangaloreAirlines traveller)
{
//Code for adding the new rout to NationalTravel's
//Travel database.
Console.WriteLine("new rout No. " +
traveller.TravelRout + " Added Sucessfully to
National Travel's Database");
}
}
public class SouthernTravels
{
public void UpdateBangaloreAirlinesRout(object Traveller)
{
if( Traveller is BangaloreAirlines)
{
AddRoutforBangaloreAirlines
((BangaloreAirlines)Traveller);
}
}
private void AddRoutforBangaloreAirlines(BangaloreAirlines
traveller)
{
//Code for adding the new rout to Southern Travel's
//Travel database.
Console.WriteLine("new rout No. " +
traveller.TravelRout + " Added Sucessfully to
SothernTravel's Database");
}
}
Now we need to implement a client for testing this application. It’s where you will attach the observers to the concrete subject.
class Client
{
[STAThread]
static void Main(string[] args)
{
BangaloreAirlines AirLines= new BangaloreAirlines("EC 2012",2230);
NationalTravels National=new NationalTravels();
SouthernTravels Southern=new SouthernTravels();
AirLines.UpdateEvent += new BangaloreAirlines.UpdateHandler(
National.UpdateBangaloreAirlinesRout);
AirLines.UpdateEvent += new BangaloreAirlines.UpdateHandler(
Southern.UpdateBangaloreAirlinesRout);
AirLines.AddNewRout();
Console.ReadLine();
}
}
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.| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 9 Mar 2004 Editor: Chris Maunder |
Copyright 2004 by Sunil Kumar K.S Everything else Copyright © CodeProject, 1999-2009 Web20 | Advertise on the Code Project |