Java has defined java.util.Observable class and java.util.Observer interface since SDK 1.0:
public class Observable extends ObjectBy inheriting Observable class and implementing Observer interface, the observer pattern is enforced. There's no Observer and Observable interface/class in .NET BCL. However it's not a difficult task to implement the observer pattern in .NET. Following code demos a simple .NET implementation of observer pattern:
{
public void addObserver(Observer o) {}
public void deleteObserver(Observer o) {}
public void notifyObservers() {}
//...
}
public interface Observer
{
public void update(Observable o, Object arg){}
}
using System;The WeatherObservable class simulates the weather changes, and keeps sending the updated temperatures to observers (subscriber). There are two subscribers in the demo code; one shows the latest temperature and the other shows alert information when temperature is in certain condition. When running the application, a console would look like:
using System.Text;
using System.Collections;
using System.Threading;
class Program
{
public interface IObserver
{
void Update(string state);
}
public interface IObservable
{
void AddObserver(IObserver o);
void NotifyObservers();
}
public class WeatherObservable : IObservable
{
private volatile int _temperature;
private ArrayList _observers = new ArrayList();
private Random rand = new Random();
public WeatherObservable()
{
new Thread(new ThreadStart(WeatherWatcher)).Start();
}
public void WeatherWatcher()
{
Console.WriteLine("Weather is changing ...");
while (true)
{
_temperature = rand.Next(-20, 40);
NotifyObservers();
Thread.Sleep(1000);
}
}
public void AddObserver(IObserver obj)
{
lock (_observers.SyncRoot)
{
_observers.Add(obj);
}
}
public void NotifyObservers()
{
lock (_observers.SyncRoot)
{
foreach (IObserver observer in _observers)
{
observer.Update(_temperature.ToString());
}
}
}
}
public class WeatherDisplayer : IObserver
{
public void Update(string state)
{
int temperature = int.Parse(state);
Console.WriteLine("Temperature now is {0}", temperature);
}
}
public class WeatherAlarm : IObserver
{
public void Update(string state)
{
int temperature = int.Parse(state);
if (temperature < -10)
{
Console.WriteLine("\nCold Alert! Temperature is {0}\n", temperature);
}
else if (temperature > 30)
{
Console.WriteLine("\nHot Alert! Temperature now is {0}\n", temperature);
}
}
}
static void Main(string[] args)
{
WeatherObservable ww = new WeatherObservable();
ww.AddObserver(new WeatherDisplayer());
ww.AddObserver(new WeatherAlarm());
Console.Read();
}
}
The above code is just a clone of Java implementation. For concise demonstration purpose, not all functions are included and synchronized notification is used.
Actually .NET uses event concept to resolve the publish-subscribe problem. An observable subject publishes its events to its subscribers which registered those events by safe and typed functions (delegate). The implementation of observer pattern can be simplified by using .NET event:
using System;Note: as shown in the code, both class member functions or static functions can be registered to an event.
using System.Text;
using System.Collections;
using System.Threading;
class Program
{
public class WeatherObservable
{
private volatile int _temperature;
Random rand = new Random();
public delegate void UpdateDelegate(int temperature);
public event UpdateDelegate TemperatureUpdateEvent;
public WeatherObservable()
{
new Thread(new ThreadStart(WeatherWatcher)).Start();
}
public void WeatherWatcher()
{
Console.WriteLine("Weather is changing ...");
while (true)
{
_temperature = rand.Next(-20, 40);
if (TemperatureUpdateEvent != null)
{
TemperatureUpdateEvent(_temperature);
}
Thread.Sleep(1000);
}
}
}
public class WeatherDisplayer
{
public void TemperatureUpdated(int temperature)
{
Console.WriteLine("Temperature now is {0}", temperature);
}
}
public class WeatherAlarm
{
public static void TemperatureUpdated(int temperature)
{
if (temperature < -10)
{
Console.WriteLine("\nCold Alert! Temperature is {0}\n", temperature);
}
else if (temperature > 30)
{
Console.WriteLine("\nHot Alert! Temperature now is {0}\n", temperature);
}
}
}
static void Main(string[] args)
{
WeatherObservable ww = new WeatherObservable();
WeatherDisplayer displayer = new WeatherDisplayer();
ww.TemperatureUpdateEvent += new WeatherObservable.UpdateDelegate(displayer.TemperatureUpdated);
ww.TemperatureUpdateEvent += new WeatherObservable.UpdateDelegate(WeatherAlarm.TemperatureUpdated);
Console.Read();
}
}