Design Patterns: The Observer Pattern

9. August 2010

From Wikipedia: In software engineering, a design pattern is a general reusable solution to a commonly occurring problem in software design. Design patterns can be a touchy subject. Sometimes described as "a solution seeking a problem," they can complicate projects where they have been implemented incorrectly through misunderstanding the pattern or by being applied to a situation that doesn't warrant that design pattern. With that said, take this article with a grain of salt. Don't look for a place to use it, but keep it as a tool for when a problem that may need it arises. With that disclaimer behind me, let me introduce you all to the Observer Pattern.

Information changes. Constantly. If there's anything the web has taught us as developers, it's that stale data can hinder a project or a decision. When fields don't properly contain the newest, most up to date values your application feels flawed, or you receive invalid output. In today's world, a wide variety of information is time sensitive so the "freshness" of your data can quickly come into question. So how do you stay up to date? First thought is to continually check the information to see if it's updated, and if it has, then you update your representation of that information. Although at first glance this approach works, it brings problems. What if the data doesn't update frequently? What if it's an internet resource and your bandwidth is limited? Do you want to choke your bandwidth with the "what if" about your data's integrity? Ideally, you'd only check for new data when you know the data has changed, but that can mean that the new data has changed and you haven't/won't reflect that change for some time. Your next best bet is that you're notified when the value changes... Wouldn't that be something? The Observer Pattern is not perfect. It doesn't scale very well, so if you have thousands of things watching for an updated value, then there will be a slow down. The few times I've found that I need to use this pattern, it's been over a network.

Let's say you were in charge of writing some software for a gas station. You had to write the software that handled displaying the price at the pumps and the sign out in front. A quick fix would be to allow the pumps and the sign to repeatedly ask your software for the newest price and display that. This makes adding or removing new pumps or other price watching hardware or software less intuitive (especially if you want to update more than a single number or string). A better way is to separate things out. Instead each device initiating a connection to ask for the newest value to stay updated, these devices could register with the gas station software, giving the software a reference of themselves and allowing themselves to be notified when the gas prices change. The desktop software would simply keep every notifiable instance that has registered with it in a List, and when the price of gas changes, it notifies everything in that list. Doing this would help keep the desktop software maintainable if the gas station obtains more gas pumps, sells gas pumps, decides to post their prices online or change their sign out in front. As long as you maintain the code to have everything interface with the central desktop software using the Observer Pattern, things can subscribe or unsubscribe and can come and go quite easily.

This particular pattern gets used a lot in WPF by binding objects to controls. When an object is bound to a control and is updated, the control is as well. Consequently, if you have a Two-Way binding, you can update the object through the use of the control, such as changing to the text of a textbox to change a name in a phone book. Although not particularly useful as an application, I threw together a project that should help express the Observer Pattern, and you'll get to see a little binding in action. This project is in C# 4.0 and Visual Studio 2010. You can get the Express Edition here.

First, I made an ObservableObject like so:

public class ObservableObject : IObservable<int>

Note the generic typing of IObservable, the int. That is the type that will be passed from the ObservableObject to the ObserverObjects, to my understanding, this can be any type. If you right click IObservable<int> and Implement Interface, it'll add a method to the body of your code file:

 

public IDisposable Subscribe(IObserver<int> observer)

 

In my definition of the Observer Pattern above, it's unclear what the returned IDisposable object represents. The returned IDisposable object will allow an ObserverObject to cancel it's subscription and will no longer be updated when the ObservableObject updates it's value. To allow this to happen, an Unsubscriber class like the following is needed (this class is seperate from the ObservableObject class we started):

 

public class Unsubscriber : IDisposable {
    private List<IObserver<int>> _observers;
    private IObserver<int> _observer;
 
    public Unsubscriber(List<IObserver<int>> observers, IObserver<int> observer) {
        this._observers = observers;
        this._observer = observer;
    }
 
    public void Dispose() {
        if (_observer != null && _observers.Contains(_observer))
            _observers.Remove(_observer);
    }
}

 

When the object Disposes, it removes the IObserver from the List of IObservers and is no longer registered with the ObservableObject. With that in place, back to the ObservableObject class. Like I said, it needs to have a collection of all the registered Observers. So we're going to create a list and update the Subscribe method so that when something subscribes to this object, it's added to this list:

 

private List<IObserver<int>> observers = new List<IObserver<int>>();
public IDisposable Subscribe(IObserver<int> observer) {
    if (!observers.Contains(observer)) {
        observers.Add(observer);
    }
    return new Unsubscriber(observers, observer);
}

 

So now, we have something that can be subscribed to, but it doesn't have anything to pass to it's subscribers and it doesn't have any code to actually pass the value to them. Let's do both of these with a property.

 

private int _value = 0;
public int Value {
    get {
        return _value;
    }
    set {
        _value = value;
        observers.ForEach(x => x.OnNext(value));
    }
}

 

The ForEach method is a fun method when used with lambda expressions like it is now. It lets you run an expression on every entry in the list, we're currently passing the property value to a as-of-now unwritten method OnNext on each of the Observers in that list. Except for the Unsubscriber class, this is all in the ObservableObject class. Both of these classes are now done. It won't compile because I've actually used ObserverObject in the code as if that file was already written, but we're just now starting that file. Remember, this object passes itself to the ObservableObject through it's Subscribe method, and is then notified when the value changes. Let's start with having it implement IObserver<T>, since we're passing an integer between the ObservableObject and it's ObserverObjects, then it needs to implement IObserver<int> specifically:

 

public class ObserverObject : IObserver<int>

 

If you right click IObserver<int> and Implement the Interface, it'll add 3 methods: OnNext, OnError, OnCompleted. OnNext is the method that's called when it receives the Next value from ObservableObject. OnError is called if the ObservableObject runs in to an error, and that exception is passed back to all ObserverObjects. Eventually, for whatever reason an ObservableObject might be done broadcasting when it's value changed, at this point it calls OnCompleted. For this simple example application, we'll only implement OnNext. The ObserverObject will need a way to store the value it received in order to display on in a UIElement, so let's create another property.

 

public int _value = -1;
public int ReceivedValue {
    get {
        return _value;
    }
    set {
        _value = value;
    }
}

 

I didn't make an automatic property on purpose, I added custom binding here for the UIElements to stay bound, I'll talk about binding in a different post. With a variable to hold the observed value and a method to receive that value, let's connect the two.

 

public void OnNext(int value) {
    ReceivedValue = value;
}

 

Now the Observer Pattern is done being implemented by these two classes. We just need to use them. Back in the MainWindow.xaml that Wpf projects always start with, let's add some controls. Three labels, three textboxes, and one button. The labels and textboxes are paired together. I placed one label and one textbox and the one button near the top of the form, and each remaining label and textbox near each side of the bottom of the window, paired together. Using the labels, the top textbox was labeled "Observable" and the other two labels labeled their corresponding textboxes as "Observer." Since I'm going to talk about binding more in-depth later, I won't go into detail now, instead, I'll tell you that I bound one ObserverObject to each of the textboxes labeled Observer, and gave the button an event to set the ObservableObject's value to whatever int you type in the Observable box.


All the code for this post is in this project.

So, your own classes can implement IObservable and can update registered IObserver objects, updating them with each value, each error, and when it's done notifying them. This pattern is about reducing the communication between objects to that which is necessary for a remote value to stay updated with a changing value.

C#, Design Pattern, Development, Source Code , , ,

blog comments powered by Disqus