fbpx

What is the observer design pattern? The observer behavioral pattern allows you to be notified of any changes instead of constantly checking. Publish/subscribe is another name that better describes how one part of your code can subscribe to changes while another part only worries about notifying subscribers when something changes.

You’ll almost certainly have many different objects in your application that all use some common information.

If this is a financial application, then you might have some daily balances that you need to show to the user. A good application will show the balances in multiple ways maybe in a table where they can be changed and in a chart where they can be viewed graphically.

If this is an adventure game, then the hero will have a position and a direction. There will usually be a main view that shows the environment that the hero is looking at. And there might be a miniature map in the corner that shows a dot for the position and rotates to show the direction.

In each of these cases, you could make one of the views dependent on the other. The chart could constantly ask the the table if anything has changed. It would have to do this rapidly over and over. The miniature map could constantly ask the main view for the position and direction over and over. Or maybe instead you decide to have the table inform the chart whenever it changes. And the main adventure view could notify the miniature map anytime the hero moves or turns.

But what do you do when the user wants a different type of chart? Or even worse, how do you handle the case where the user zooms in on the miniature map and makes it go full screen so there’s no more main view?

The solution is to refactor the data into its own class that’s not responsible for any of the views. Then any class that is interested to know when the data changes can call a method on the data class to attach a callback method which the data class will call. This method will be called update. The data class defines what the update method looks like because it’ll be the one calling the method. The data class actually just calls however many update methods were attached one at a time until it’s called all of them.

Once this is done, each of the views become equals and are no longer dependent on each other. They are each waiting to have their update method called. The episode describes more details and gives some other design considerations you should be aware of.

If you’d like to read the book that describes this pattern along with diagrams and sample code, then you can find Design Patterns at the Resources page. You can find all my favorite books and resources at this page to help you create better software designs.

Listen to the full episode or you can also read the full transcript below.

Transcript

The basic description says that this pattern defines a one-to-many relationship between objects so that when an object changes, all dependent objects are notified and can update themselves. This description is a little hard to understand, so let me explain.

I’m sure you’ve heard the stories of parents taking their kids on vacation and getting endless questions, “Are we there yet?” Over and over. You might think we’d outgrow this but evidently not when it comes to software.

In many ways, even the name of this pattern is wrong.

Just think what it means to observe something.

Really observe it. Your whole attention is devoted to watching and examining this thing. That’s not what this pattern is about at all.

Another common name for this pattern is publish/subscribe which is better. At least when you subscribe to a magazine, you don’t have to observe your local newsstand each day to know when the next edition has been published. It just shows up in your mailbox.

Even though the name might be a bit misleading, there’s nothing wrong with this pattern itself. It’s actually very important to get this pattern correct early on when developing software. You’ll almost certainly have many different objects in your application that all use some common information.

If this is a financial application, then you might have some daily balances that you need to show to the user. A good application will show the balances in multiple ways maybe in a table where they can be changed and in a chart where they can be viewed graphically.

If this is an adventure game, then the hero will have a position and a direction. There will usually be a main view that shows the environment that the hero is looking at. And there might be a miniature map in the corner that shows a dot for the position and rotates to show the direction.

In each of these cases, you could make one of the views dependent on the other. The chart could constantly ask the table if anything has changed. It would have to do this rapidly over and over. The miniature map could constantly ask the main view for the position and direction over and over.

That’s silly, right? So maybe instead you decide to have the table inform the chart whenever it changes. Better? And the main adventure view could notify the miniature map anytime the hero moves or turns.

But what do you do when the user wants a different type of chart? Or even worse, how do you handle the case where the user zooms in on the miniature map and makes it go full screen so there’s no more main view?

We need a better solution and questions like this can lead to some major design decisions.

That’s why you need to understand this pattern before you end up coding yourself into a trap. All it takes is a slight shift in our thinking. We just need to stop asking, “Are we there yet?”

I’ll explain how to implement this pattern right after this message from our sponsor.

( Message from Sponsor )

The first thing to do is get the data itself, the stuff that can change, into a data class that has no responsibility to display this information to the user. Make it do one thing and do it well, manage the data. This would be the financial balances or the hero’s position.

Then provide a way for any other class to express a desire to be notified when something changes.

Have you ever called the customer support number for a large company? Some make you wait and listen to hold music which is no fun. Unless you like that sort of thing. But a better system will ask you if you would like to be called back when it’s your turn.

What does this notification look like?

You get to decide that. It could be as simple as, “Hey, something changed!” to as elaborate as, “The hero’s new position is at coordinates 382 comma 490, and the hero used to be at location 381 comma 490.” This is just a method that you define in your data class for other classes to actually implement. Let’s call this method update. Your data class will not have an update method. It just defines what this update method should look like. In other words, what are the method parameters? A really simple update method needs no parameters and returns void. A more complicated update method could have four integers for the new and old hero positions.

If the data class doesn’t implement this method, then who does? These are the observer classes which is where this pattern gets its name. They’re not really observing anything though. They can go about their business as normal and respond whenever their update method gets called.

So who calls the update method?

That’s the job of the data class. It knows when its data changes and can call potentially many update methods. This is the beauty of this pattern. The data class doesn’t care about how many observers there are, or even if there are any observers. Anytime something changes, it can start calling update methods one at a time until it’s called all of them.

Okay, so how does the data class know about the update methods? All I’ve described so far is that the data class defines what the update method should look like. But in order to call update methods, the data class is going to need actual instances of the observers.

To do this, the data class needs a couple more methods that it will implement. The first is called attach and the second is called detach. Now anytime some class is interested to know when the data changes, all it has to do is call attach and provide its update method. If it no longer wants to be notified, it can call detach. This is what the chart class and the miniature map class need to do. They each call attach on their data classes so they’ll be able to be notified whenever a change happens. But they’re not the only classes that need to call attach. With this pattern even the main table view and the main hero view need to know when the data changes.

This pattern makes all of these views equals.

Need a new type of chart? No problem, just implement the update method and call attach. The main table no longer needs to know about any of the charts.

Need to zoom the miniature map? No problem because it no longer depends on the main hero view at all.

All of these classes are now dependent on the data class only.

There are some other things to consider before I end this explanation.

How does the data class know when to call the various update methods?

There’s no right answer to this. You could have the data class itself call the update methods anytime a property changes. This can lead to a very chatty dialog though, especially when many properties need to be changed. Each change will end up calling all the update methods.

Or maybe you expose an actual method on the data class called notify. Then you could let some other class call notify at the right time after it completes a bunch of data changes. This can batch many update calls to each of the observers but opens your design to possible bugs if some class forgets to call the notify method. You could end up changing the data in one view but still showing the old data in the other views because they were never updated through the notify method.

Another big consideration is how will you handle subscriptions that are no longer valid?

Let’s say some chart class calls attach but then goes away without ever calling detach. You’re left with an update method for an instance of a class that no longer exists. This is likely to cause your application to crash. Sure, you can always just say, “Don’t do that.” and test your application to make sure that no classes actually forget to call detach. But a little defensive coding is always a good idea. You could use shared smart pointers to handle this. That’ll need to be a future episode.

The last thing I’ll mention today is how to allow an observer to attach to multiple data classes.

Imagine you need to call several large companies and you leave your callback number with each of them. Now, in real life this is not a problem because when a company calls you back, you’re able to speak directly with the representative. Actually it can cause a problem because what do you do when you answer one callback and while you’re speaking to the agent, one of your other companies calls back. All you hear is the beep that another call is trying to connect. You don’t know which one.

That’s fairly close to the problem we have now with the update method. If your chart is subscribed to multiple data classes and it gets called on the update method, how will it know which data class was changed? A simple solution is to modify the update method to allow the data class to send a pointer or reference to itself when it makes the call. Now when your chart’s update method is called, it will be able to test the source to know which data was changed.