BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

Observer Design Pattern

The observer pattern is a design pattern that defines a link between objects so that when one object's state changes, all dependent objects are updated automatically. This pattern allows communication between objects in a loosely coupled manner.

Example Observer

In this section we will create a simple example of the observer design pattern using C#. This example will implement the message logging system described earlier in the article. The subject will be the class that receives messages to be logged and holds the details of the last message in its state.

We will create two observer classes to simulate emailing messages to an administrator or logging to the event log. In both cases we will omit the logging code, as this would over-complicate the sample. Instead we will write a message to the console.

The code for the logging system is as follows:

public abstract class EventReceiverBase
{
    private ArrayList _monitors = new ArrayList();

    public void Attach(EventMonitor monitor)
    {
        _monitors.Add(monitor);
    }

    public void Detach(EventMonitor monitor)
    {
        _monitors.Remove(_monitors);
    }

    public void Notify()
    {
        foreach (EventMonitor monitor in _monitors)
        {
            monitor.Update();
        }
    }
}


public class EventReceiver : EventReceiverBase
{
    private string _lastMessage;

    public string GetLastMessage()
    {
        return _lastMessage;
    }

    public void LogMessage(string message)
    {
        _lastMessage = message;
        Notify();
    }
}


public abstract class EventMonitor
{
    public abstract void Update();
}


public class EventEmailer : EventMonitor
{
    private EventReceiver _receiver;

    public EventEmailer(EventReceiver receiver)
    {
        _receiver = receiver;
    }

    public override void Update()
    {
        string message = _receiver.GetLastMessage();
        Console.WriteLine("Emailing: {0}", message);
    }
}


public class EventLogger : EventMonitor
{
    private EventReceiver _receiver;

    public EventLogger(EventReceiver receiver)
    {
        _receiver = receiver;
    }

    public override void Update()
    {
        string message = _receiver.GetLastMessage();
        Console.WriteLine("Logging: {0}", message);
    }
}

Testing the Observer

To test the observers we can use a console application and execute code from the Main method. The first code to include in the Main method will simulate the situation where no observer (EventMonitor) has subscribed to the subject (EventReceiver). In this case, logging a message has no effect. Run the following code to see that there is no output because nothing is monitoring the subject.

EventReceiver receiver = new EventReceiver();
receiver.LogMessage("Message with no observers.");

For the second example, execute the code below. This creates a receiver and attaches an observer that sends email when a message is logged.

EventReceiver receiver = new EventReceiver();
EventMonitor emailMonitor = new EventEmailer(receiver);
receiver.Attach(emailMonitor);

receiver.LogMessage("Message with one observer.");

/* OUTPUT

Emailing: Message with one observer.

*/

As described above, the observer pattern allows multiple observers to subscribe to changes in a single subject. We can demonstrate this by adding a second observer, this time an event monitor that sends messages to the event log:

EventReceiver receiver = new EventReceiver();
EventMonitor emailer = new EventEmailer(receiver);
receiver.Attach(emailer);
EventMonitor logger = new EventLogger(receiver);
receiver.Attach(logger);

receiver.LogMessage("Message with two observers.");

/* OUTPUT

Emailing: Message with two observers.
Logging: Message with two observers.

*/
7 June 2009