Published: 22 Aug 2008
By: Granville Barnett
Download Sample Code

In this part of the design patterns series we will take a look at the observer design pattern.

Contents [hide]

Introduction

The observer pattern is incredibly useful, so useful in fact that it has found itself used all over the place in .NET. Underlying the observer pattern is a simple concept; it’s merely a design to accommodate a one-to-many relationship in a loosely coupled fashion.

Design Patterns Series

  • Part 1 Learn how to design more robust and maintainable code by incorporating design patterns into your software projects.
  • Part 2 This part shows the observer design pattern.
  • Part 3 In this part you will learn about the factory pattern.
  • Part 4 This part of the design patterns covers the singleton pattern.
  • Part 5 In this part of the design patterns series we investigate the command pattern and its uses.
  • Part 6 In this part of the design patterns series we will look at the adapter pattern.
  • Part 7 In this part of the design patterns series we will take a look at the template pattern.
  • In this article we will look at the design of the observer pattern. We will implement our own version of the observer pattern, and then we will look briefly at using .NET events to achieve the same result.

    What is the observer pattern?

    As mentioned in the introduction the observer pattern allows us to implement a one-to-many relationship in a loosely coupled fashion. Loosely coupled means that the objects don’t know much about each other, they know just enough to get the job done.

    To illustrate the observer pattern imagine you want to subscribe to Time magazine. You go to the Time magazine website, fill out a few forms and now you are subscribed for a time period of your choosing. In this scenario we will say that Time magazine is the subject, and you, along with all other subscribers are the observers. When a new issue of Time magazine comes out you will be notified via the physical receipt of the latest issue. If we cast our minds back to a time before we were subscribers of the magazine we will remember that when a new issue came out we didn’t receive a copy, and we probably weren’t even told about the availability of a new issue.

    In the preceding example scenario we identified that Time magazine was the subject, and we (the people who have paid to receive a copy of the magazine each month) were the subscribers. Unless it is not totally obvious, the subject represents the one in our one-to-many relationship. The subscribers of the magazine are represented by the many.

    When the subject has something interesting to inform its observers it will send a notification to each of them. Using our example the notification would be in the form of a copy of the magazine. In the software world the notification may be an object that contains various properties that the subject expects the observers may be interested in. We can apply this methodology to the event arguments often used in .NET. For example when you subscribe to an event on a user interface (UI) control in one of the three UI stacks (WPF, Win Forms, or ASP.NET) the event will often be accompanied with some data specific to that event – data that the observers will probably find very useful. Events aren’t limited to UI controls; you will find events in many types, for example System.Data.SqlClient.SqlCommand exposes an event StatementCompleted that is raised when the underlying SQL query has completed executing.

    The Design

    By just thinking about the previous example given we might be leaning towards saying that the subject would contain a list of objects to notify, and you would be correct in doing so. Registering an interest in the subject would simply add that object to the list of observers in the observers list contained within the subject. Similarly unregistering an observer from notifications would simply be a case of removing that observer from the list of observers to notify in the subject.

    For our example we will mimic a very common scenario that the crew of the USS Enterprise often found themselves in. Scotty, the infamous engineer down in the engine room will be the subject. Our observers will comprise of the captain (could be Kirk, could be Picard – as an Englishman I am biased towards Picard, or Jean-Luc as he was known to those close to him), and their number one – I’ll go with Riker. To summarize then this is our scenario: we have just been attacked by a hostile Klingon Bird of Prey and we are temporarily limited to our impulse drive, we are relying on good ‘ol Scotty to inform the good captain and Riker when the warp engine is back online. As you can expect the captain and Riker really do need that notification when the warp engine is back online. The design we have is as follows:

    Figure 1: Our observer pattern design

    Our observer pattern design

    As you can see from the previous Figure Scotty contains zero-or-more IObserver’s. For the purposes of keeping things simple we will use a List<IObserver> to store all the observers that care about what Scotty has to say. You will notice that in order to get into the list of observers we need to call the Subscribe method. This method simply adds an IObserver to the list of observers in the Scotty object. We have omitted an Unsubscribe method to make the sample as concise and as clear as possible.

    What happens when Scotty has something to tell those who are interested in what he has to say? In our simple example we will just traverse each IObserver in the observers list and call Update on each of them. Because the Captain and NumberOne differ in the way in which they react to notifications from Scotty we have used a class for each. All we care about is that the observers implement IObserver.

    We mentioned earlier that often we want to send a bit of information along with the notification. In our example scenario we will send such information as a string (this will suffice to demonstrate the point). To allow this we will modify the Notify method to take a string parameter.

    Figure 2: Adding a way to pass some information to the observers

    Adding a way to pass some information to the 

observers

    Implementing our design

    Because we have already done all the heavy lifting the implementation is very straightforward. If you have understood the design, you will understand the code. The code listings for each file are as follows:

    Listing 1: IObserver.cs

    Listing 2: ISubject.cs

    Listing 3: Scotty.cs

    Listing 4: Captain.cs

    Listing 5: NumberOne.cs

    Listing 6: Program.cs

    One of the main things that we really should talk about is the call to scotty.NotifyObservers in Program.cs. This is used to synthetically force notifications to the observers, in reality this would be done internally within the subject. It is done in this fashion simply to make the point clearer.

    If you run the project you will see the following output via the console.

    Figure 3: Result of running the sample program

    Result of running the sample program

    One thing that we haven’t talked about so far is that of relying upon the order in which notifications are made. In our example observers who are added first will be notified first and so on. You should never code to rely on such occurrences with the observer pattern; doing so would not be loosely coupled.

    Aren’t events already in .NET?

    Yes. Events in .NET are based upon delegates. Using events in .NET is very simple. Typically you will:

    Define a type that represents the data associated with the event

    Create a public event member

    Create a method responsible for raising that event

    For the first point you must derive from System.EventArgs. For example if we wanted to associate some data with the warp engine coming back online we could do so in a class called WarpEngineOnlineEventArgs that derived from System.EventArgs. This event would no doubt carry critical information that each observer would expect to get with each notification.

    The second point is very straightforward, all we do is declare a public event member like below:

    Why public? The compiler will take care of the rest. Upon compilation the C# compiler will make the member private and generate two public methods:

    • add_WarpEngineOnline
    • remove_WarpEngineOnline

    The add method will register the interest of an observer, the remove method will unregister that interest. When we register a methods interest we do so by using a delegate. The delegate is a pointer to the method to invoke when that event is raised. When the add_WarpEngineOnline method is called that delegate is added to a list of delegates to invoke when the event is raised. Calling remove_WarpEngineOnline will remove the correct delegate from the list of delegates to invoke when that event is raised.

    For the last point we simply need a method that invokes the event. This is very straightforward; we call the event and then provide the required arguments. As well as providing any additional information with the event in the form of EventArgs we can also provide information as to the object that raised the event, or rather the sender.

    The following code is the same example we used previously but using .NET events.

    Listing 7: WarpEngineOnlineEventArgs.cs

    Listing 8: Scotty.cs

    Listing 9: Captain.cs

    Listing 10: NumberOne.cs

    Listing 11: Program.cs

    If you run the project you will see the same output. Notice that instead of calling the add_Xxx or remove_Xxx methods directly to subscribe to the WarpEngineOnline event we simply use the += operator. This operator has been overloaded to call the add_Xxx event. Similarly the -= operator will call the remove_Xxx method to unsubscribe from the event.

    Figure 4: += Operator overloaded

    += Operator overloaded

    Summary

    In this part of the design patterns series we have looked at the observer pattern. We have implemented our own primitive version of the observer pattern, as well as using events in .NET. The observer pattern is very useful for modeling one-to-many relationships in a loosely coupled fashion and is used throughout many mainstream frameworks.

    The next part of the series will focus on the factory pattern.

    <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Granville Barnett

    Sorry, no bio is available

    This author has published 32 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Introduction to StructureMap
    Have you heard of StructureMap, generally know what it’s for, and want to know how to get started qu...
    DI Patterns: Constructor Injection
    In this article, an excerpt from the book "Dependency Injection in .NET", we will take a detailed lo...
    The Command Pattern
    In this article I will provide a quick refresher on what the command pattern is used for, how it wor...
    TypeMock’s Arrange-Act-Assert
    Brian Mains discusses how to implement the Arrange-Act-Assert pattern in TypeMock.
    Key Process Patterns
    This article, based on chapter 2 of Specification by Example, presents effective patterns for softwa...

    You might also be interested in the following related blog posts


    Learn design patterns from real projects: JBoss case study (Part 1). read more
    Designing a Windows 8 Metro style app starting from an existing Windows Phone app Design Case Study Part 1 read more
    Oredev Wrap-Up read more
    Introducing SharePoint 2010 Training at U2U read more
    The Underground at PDC read more
    12 ASP.NET MVC Best Practices read more
    Screencast Whats new in the Entity Data Model Designer in VS2010 read more
    What needed to be monitored to get better Governance read more
    SharePoint 2010 Workflow read more
    Formatting Text in RadControls for WinForms Q3 2009 read more
    Top
     
     
     

    Please login to rate or to leave a comment.