C# Design Patterns - Observer Pattern

We’ve covered a couple of design patterns so far in our series. I have been enjoying writing these posts and I hope you have enjoyed reading them or at least got something out of them

In this post we are going to take a look at the Observer pattern.

What Is The Observer Pattern?

The Observer pattern is a way for an object to notify all of it’s dependants when something changes based on a one to many relationship.

The Situation

Continuing to use our city dog registration software senario, one of the project’s requirements is that the dog’s owner’s be notified whenever a dog is processed for an infraction (i.e. picked up by the dog catcher). The Observer pattern is perfectly suited to solve this problem.

Setting Up Our Observer

First before we create our Observer we need to define some classes and interfaces that we will need to use with the Observer.

public interface IInfraction {
    string Type { get; set; }
    int Id { get; set; }
    DateTime Date { get; set; }
    string Reason { get; set; }
    double Fee { get; set; }
}

public class Infraction : IInfraction {
    public string Type { get; set; }

    int Id { get; set; }

    DateTime Date { get; set; }
    string Reason { get; set; }
    double Fee { get; set; }
}

public interface IOwner {
    int Id { get; set; }

    string FirstName { get; set; }

    string LastName { get; set; }

    string EmailAddress { get; set; }
}

public class Owner : IOwner {
    public Owner() { }
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string EmailAddress { get; set; }

}

The above code defines an infraction and an owner for our Observer to use. Now we can setup our Observer and the notifications when a dog gets an infraction.

public interface IDog {
    int Id { get; set; }
    string Name { get; set; }
    void AddInfraction(IInfraction infraction);
    void AddOwner(IOwner owner);
}

public class Dog : IDog {
    private IList<IOwner> _owners;
    private IList<IInfraction> _infractions;

    public Dog() {
        _owners = new List<Owner>();
        _infractions = new List<Infraction>();
    }

    public void AddOwner(IOwner owner) {
        _owners.Add(owner);
    }

    public void AddInfraction(IInfraction infraction) {
        _infractions.Add(infraction);

        //notify owners of infraction : the Observer
        foreach(IOwner owner in _owners) {
            string message = “Dear ” + owner.FirstName + “,\n\n” +
                “We are writing you to inform you that there has been an incident with your dog, “ +
                this.Name + “, and that the city had to get involved.\n\n” +
                “Your dog is being held at the city dog pound for the following reason: “ + infraction.Reason + “.” +
                “You can pick them up anytime. There will be a fee of $” + infraction.Fee + ” applied.”;
            MessageService.SendEmail(owner.EmailAddress, “cityhall@fictionalcity.com”, message);
        }
    }

    public int Id { get; set; }
    public string Name { get; set; }
}

You can see the this pattern at work in the AddInfraction method. Everytime this method is called an infraction is added to the dog’s record and all the owners are sent an email detailing the infraction and where to pick up their dog. It’s nice when you can structure your code to handle situations automatically, for you and your clients.

If you enjoyed this post be sure to grab the RSS feed or follow me on Twitter to get notifications of new posts. Also, check out other posts in this series below.

The C# Design Patterns Series

Part 1 - An Overview
Part 2 - The Decorator Pattern
Part 3 - The Abstract Factory Pattern
Part 4 - The Observer Pattern

kick it on DotNetKicks.com

11 comments on this post

Steve says:
Jan 29, 2009 - 03:01:56

This might be the normal way of doing it, but in .NET we can use events to do the same thing but easier :)

Justin says:
Jan 29, 2009 - 03:01:22

That’s true but this is an example of the Observer pattern :D

Jan 29, 2009 - 09:01:29

Hi,
this is really a nice blog that I often visit.
Yeah, as Steve said same can be done using Events in dotnet and I thing which is a more preferable way. It has mainly two benefits (which you might already be aware) over a classical way.
1. You don’t need to have a collection that would contain list of the observers.
2. And you do not need to iterate over a collection and invoke method.
here is my implementation.
using System;

namespace ObserverPatternTest
{
public delegate void NotifyObserverEventHandler(string Message);
class Program
{
static void Main(string[] args)
{
Bell bell=new Bell();
Student std=new Student();
bell.AddObserver(std);
Teacher teacher=new Teacher();
bell.AddObserver(teacher);
bell.Ring(”This is a First Period”);
bell.RemoveObserver(std);
bell.Ring(”This is a presentation time”);
Console.ReadLine();

}
}

public interface INotifier
{
event NotifyObserverEventHandler NotifyChanged;
void AddObserver(IObserver observer);
void RemoveObserver(IObserver observer);
}

public class Bell : INotifier
{
public void Ring(string Message)
{
if(NotifyChanged!=null)
{
NotifyChanged(Message);
}
}

public event NotifyObserverEventHandler NotifyChanged;
public void AddObserver(IObserver observer)
{
this.NotifyChanged += observer.Update;
}
public void RemoveObserver(IObserver observer)
{
this.NotifyChanged -= observer.Update;
}
}

public interface IObserver
{
void Update(string Message);
}
public class Student : IObserver
{
public void Update(string Message)
{
Console.WriteLine();
Console.WriteLine(”Student Received:”);
Console.WriteLine(Message);
}
}
public class Teacher : IObserver
{
public void Update(string Message)
{
Console.WriteLine();
Console.WriteLine(”Teacher Received:”);
Console.WriteLine(Message);
}
}
}

Yngve says:
Jan 30, 2009 - 01:01:29

Great article-series, but wouldn’t it be better to further extract the logic for AddInfraction away from the Dog-model (i know this is not part of the observer-pattern). This way you could leave both the Infraction and the Dog classes to keep only data, and no logic… Just a thought…

Mike says:
Jan 30, 2009 - 09:01:04

I think it would be better to raise an event and pass the infraction as parameter of the event. You can then let each observer decide what to do, either generate a message to email or store parts of the data in other ways. This would further decouple the implementation.

gery says:
Feb 12, 2009 - 03:02:53

Good Post

Mar 8, 2009 - 06:03:29

This post has good and valuable information, Is nice to see some good articles like this one, thank you.

John says:
Mar 10, 2009 - 04:03:36

I love the simplicity of this example. Thanks! Keep up the good work!

Apr 14, 2009 - 09:04:33

Please update the links under The C# Design Patterns Series. I almost stopped at this post not realizing there were more.

Very cool! Thx