Chapter 2. The Observer Pattern: Keeping your Objects in the Know

Images

You don’t want to miss out when something interesting happens, do you? We’ve got a pattern that keeps your objects in the know when something they care about happens. It’s the Observer Pattern. It is one of the most commonly used design patterns, and it’s incredibly useful. We’re going to look at all kinds of interesting aspects of Observer, like its one-to-many relationships and loose coupling. And, with those concepts in mind, how can you help but be the life of the Patterns Party?

Congratulations!

Note

Your team has just won the contract to build Weather-O-Rama, Inc.’s next-generation, internet-based Weather Monitoring Station.

Images

The Weather Monitoring application overview

Let’s take a look at the Weather Monitoring application we need to deliver—both what Weather-O-Rama is giving us, and what we’re going to need to build, or extend. The system has three components: the weather station (the physical device that acquires the actual weather data), the WeatherData object (that tracks the data coming from the Weather Station and updates the displays), and the display that shows users the current weather conditions:

Images

The WeatherData object was written by Weather-O-Rama and knows how to talk to the physical Weather Station to get updated weather data. We’ll need to adapt the WeatherData object so that it knows how to update the display. Hopefully Weather-O-Rama has given us hints for how to do this in the source code. Remember, we’re responsible for implementing three different display elements: Current Conditions (shows temperature, humidity, and pressure), Weather Statistics, and a simple Forecast.

Note

So, our job, if we choose to accept it, is to create an app that uses the WeatherData object to update three displays for current conditions, weather stats, and a forecast.

Unpacking the WeatherData class

Note

Let’s check out the source code attachments that Johnny Hurricane, the CEO, sent over. We’ll start with the WeatherData class:

Images
Note

So, our job is to alter the measurementsChanged() method so that it updates the three displays for current conditions, weather stats, and forecast.

Our Goal

We know we need to implement a display and then to have the WeatherData update that display each time it has new values, or, in other words, each time the measurementsChanged() method is called. But how? Let’s think through what we’re trying to acheive:

  • We know the WeatherData class has getter methods for three measurement values: temperature, humidity, and barometric pressure.

  • We know the measurementsChanged() method is called any time new weather measurement data is available. (Again, we don’t know or care how this method is called; we just know that it is called.)

  • We’ll need to implement three display elements that use the weather data: a current conditions display, a statistics display, and a forecast display. These displays must be updated as often as the WeatherData has new measurements.

  • To update the displays, we’ll add code to the measurementsChanged() method.

Images

Stretch Goal

But let’s also think about the future—remember the constant in software development? Change. We expect, if successful, there will be more than three displays in the future, in fact, why not create a marketplace for additional displays? So, how about we build in:

  • Expandability—other developers may want to create new custom displays. Why not allow users to add (or remove) as many display elements as they want to the application. Currently, we know about the initial three display types (current conditions, statistics, and forecast) but we expect a vibrant marketplace for new displays in the future.

Taking a first, misguided SWAG at the Weather Station

Here’s a first implementation possibility—as we’ve discussed we’re going to add our code to the measurementsChanged() method in the WeatherData class:

Images

What’s wrong with our implementation anyway?

Think back to all those Chapter 1 concepts and principles—which are we violating, and which are we not? Think in particular about the effects of change on this code. Let’s work through our thinking as we look at the code:

Images
Images

Good idea. Let’s take a look at Observer, then come back and figure out how to apply it to the Weather Monitoring app.

Meet the Observer Pattern

Note

You know how newspaper or magazine subscriptions work:

  1. A newspaper publisher goes into business and begins publishing newspapers.

  2. You subscribe to a particular publisher, and every time there’s a new edition it gets delivered to you. As long as you remain a subscriber, you get new newspapers.

  3. You unsubscribe when you don’t want papers anymore, and they stop being delivered.

  4. While the publisher remains in business, people, hotels, airlines, and other businesses constantly subscribe and unsubscribe to the newspaper.

Images

Publishers + Subscribers = Observer Pattern

Note

If you understand newspaper subscriptions, you pretty much understand the Observer Pattern, only we call the publisher the SUBJECT and the subscribers the OBSERVERS.

Let’s take a closer look:

Images

A day in the life of the Observer Pattern

A Duck object comes along and tells the Subject that he wants to become an observer.

Duck really wants in on the action; those ints Subject is sending out whenever its state changes look pretty interesting...

Images

The Duck object is now an official observer.

Duck is psyched... he’s on the list and is waiting with great anticipation for the next notification so he can get an int.

Images

The Subject gets a new data value!

Now Duck and all the rest of the observers get a notification that the Subject has changed.

Images

The Mouse object asks to be removed as an observer.

The Mouse object has been getting ints for ages and is tired of it, so he decides it’s time to stop being an observer.

Images

Mouse is outta here!

The Subject acknowledges the Mouse’s request and removes him from the set of observers.

Images

The Subject has another new int.

All the observers get another notification, except for the Mouse who is no longer included. Don’t tell anyone, but the Mouse secretly misses those ints... maybe he’ll ask to be an observer again some day

Images

Five-minute drama: a subject for observation

Images

In today’s skit, two enterprising software developers encounter a real live head hunter...

Images
  1. Software Developer #1

    Images
  2. Headhunter/Subject

    Images
  3. Software Developer #2

    Images
  4. Subject

  5. Meanwhile, for Lori and Jill life goes on; if a Java job comes along, they’ll get notified. After all, they are observers.

    Images
  6. Subject

    Images
  7. Observer

    Images
  8. Observer

    Images
  9. Subject

Two weeks later...

Images

Jill’s loving life, and no longer an observer. She’s also enjoying the nice fat signing bonus that she got because the company didn’t have to pay a headhunter.

Images

But what has become of our dear Lori? We hear she’s beating the headhunter at his own game. She’s not only still an observer, she’s got her own call list now, and she is notifying her own observers. Lori’s a subject and an observer all in one.

The Observer Pattern defined

A newspaper subscription, with its publisher and subscribers, is a good way to visualize the pattern.

In the real world, however, you’ll typically see the Observer Pattern defined like this:

Note

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

Let’s relate this definition to how we’ve been thinking about the pattern:

Images
Note

The Observer Pattern defines a one-to-many relationship between a set of objects.

When the state of one object changes, all of its dependents are notified.

The subject and observers define the one-to-many relationship. We have one subject, who notifies many observers when something in the subject changes. The observers are dependent on the subject—when the subject’s state changes, the observers are notified.

As you’ll discover, there are a few different ways to implement the Observer Pattern, but most revolve around a class design that includes Subject and Observer interfaces.

The Observer Pattern: the Class Diagram

Let’s take a look at the structure of the Observer Pattern, complete with its Subject and Observer classes. Here’s the class diagram:

Images

The Power of Loose Coupling

When two objects are loosely coupled, they can interact, but they typically have very little knowledge of each other. As we’re going to see, loosely coupled designs often give us a lot of flexibility (more on that in a bit). And, as it turns out, the Observer Pattern is a great example of loose coupling. Let’s walk through all the ways the pattern achieves loose coupling:

First, the only thing the subject knows about an observer is that it implements a certain interface (the Observer interface). It doesn’t need to know the concrete class of the observer, what it does, or anything else about it.

We can add new observers at any time. Because the only thing the subject depends on is a list of objects that implement the Observer interface, we can add new observers whenever we want. In fact, we can replace any observer at runtime with another observer and the subject will keep purring along. Likewise, we can remove observers at any time.

We never need to modify the subject to add new types of observers. Let’s say we have a new concrete class come along that needs to be an observer. We don’t need to make any changes to the subject to accommodate the new class type; all we have to do is implement the Observer interface in the new class and register as an observer. The subject doesn’t care; it will deliver notifications to any object that implements the Observer interface.

Images

We can reuse subjects or observers independently of each other. If we have another use for a subject or an observer, we can easily reuse them because the two aren’t tightly coupled.

Changes to either the subject or an observer will not affect the other. Because the two are loosely coupled, we are free to make changes to either, as long as the objects still meet their obligations to implement the subject or observer interfaces.

Images
Note

Loosely coupled designs allow us to build flexible OO systems that can handle change because they minimize the interdependency between objects.

Cubicle conversation

Back to the Weather Station project. Your teammates have already begun thinking through the problem...

Images

Mary: Well, it helps to know we’re using the Observer Pattern.

Sue: Right... but how do we apply it?

Mary: Hmm. Let’s look at the definition again:

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Mary: That actually makes some sense when you think about it. Our WeatherData class is the “one” and our “many” is the various display elements that use the weather measurements.

Sue: That’s right. The WeatherData class certainly has state... that’s the temperature, humidity, and barometric pressure, and those definitely change.

Mary: Yup, and when those measurements change, we have to notify all the display elements so they can do whatever it is they are going to do with the measurements.

Sue: Cool, I now think I see how the Observer Pattern can be applied to our Weather Station problem.

Mary: There are still a few things to consider that I’m not sure I understand yet.

Sue: Like what?

Mary: For one thing, how do we get the weather measurements to the display elements?

Sue: Well, looking back at the picture of the Observer Pattern, if we make the WeatherData object the subject, and the display elements the observers, then the displays will register themselves with the WeatherData object in order to get the information they want, right?

Mary: Yes... and once the Weather Station knows about a display element, then it can just call a method to tell it about the measurements.

Sue: We gotta remember that every display element can be different... so I think that’s where having a common interface comes in. Even though every component has a different type, they should all implement the same interface so that the WeatherData object will know how to send them the measurements.

Mary: I see what you mean. So every display will have, say, an update() method that WeatherData will call.

Sue: And update() is defined in a common interface that all the elements implement...

Designing the Weather Station

How does this diagram compare with yours?

Images

Implementing the Weather Station

Alright we’ve had some great thinking from Mary and Sue (from a few pages back) and we’ve got a diagram that details the overall structure of our classes. So, let’s get our implemention of the weather station underway. Let’s start with the interfaces:

Images

Implementing the Subject interface in WeatherData

Remember our first attempt at implementing the WeatherData class at the beginning of the chapter? You might want to refresh your memory. Now it’s time to go back and do things with the Observer Pattern in mind:

Note

REMEMBER: we don’t provide import and package statements in the code listings. Get the complete source code from http://wickedlysmart.com/head-first-design-patterns/.

Images

Now, let’s build those display elements

Now that we’ve got our WeatherData class straightened out, it’s time to build the Display Elements. Weather-O-Rama ordered three: the current conditions display, the statistics display, and the forecast display. Let’s take a look at the current conditions display; once you have a good feel for this display element, check out the statistics and forecast displays in the code directory. You’ll see they are very similar.

Images

Power up the Weather Station

Images
  1. First, let’s create a test harness.

    The Weather Station is ready to go. All we need is some code to glue everything together. We’ll be adding some more displays and generalizing things in a bit. For now, here’s our first attempt:

    Images
  2. Run the code and let the Observer Pattern do its magic.

    Images
Images

Tonight’s talk: A Subject and Observer spar over the right way to get state information to the Observer.

Subject: Observer:
I’m glad we’re finally getting a chance to chat in person.  
  Really? I thought you didn’t care much about us Observers.
Well, I do my job, don’t I? I always tell you what’s going on... Just because I don’t really know who you are doesn’t mean I don’t care. And besides, I do know the most important thing about you—you implement the Observer interface.  
  Yeah, but that’s just a small part of who I am. Anyway, I know a lot more about you...
Oh yeah, like what?  
  Well, you’re always passing your state around to us Observers so we can see what’s going on inside you. Which gets a little annoying at times...
Well, excuuuse me. I have to send my state with my notifications so all you lazy Observers will know what happened!  
  Okay, wait just a minute here; first, we’re not lazy, we just have other stuff to do in between your oh-so-important notifications, Mr. Subject, and second, why don’t you let us come to you for the state we want rather than pushing it out to just everyone?
Well... I guess that might work. I’d have to open myself up even more, though, to let all you Observers come in and get the state that you need. That might be kind of dangerous. I can’t let you come in and just snoop around looking at everything I’ve got.
  Why don’t you just write some public getter methods that will let us pull out the state we need?
Yes, I could let you pull my state. But won’t that be less convenient for you? If you have to come to me every time you want something, you might have to make multiple method calls to get all the state you want. That’s why I like push better... then you have everything you need in one notification.  
  Don’t be so pushy! There are so many different kinds of us Observers, there’s no way you can anticipate everything we need. Just let us come to you to get the state we need. That way, if some of us only need a little bit of state, we aren’t forced to get it all. It also makes things easier to modify later. Say, for example, you expand yourself and add some more state. If you use pull, you don’t have to go around and change the update calls on every observer; you just need to change yourself to allow more getter methods to access our additional state.
Well as I like to say, don’t call us, we’ll call you! But, I’ll give it some thought.  
  I won’t hold my breath.
You never know, hell could freeze over.  
  I see, always the wise guy...
Indeed.  

Looking for the Observer Pattern in the Wild

The Observer Pattern is one of the most common patterns in use, and you’ll find plenty of examples of the pattern being used in many libraries and frameworks. If we look at the Java Development Kit (JDK) for instance, both the JavaBeans and Swing libraries make use of the Observer Pattern. The pattern’s not limited to Java either; it’s used in JavaScript’s events and in Cocoa and Swift’s Key-Value Observing protocol, to name a couple of other examples. One of the advantages of knowing design patterns is recognizing and quickly understanding the design movitation in your favorite libraries. Let’s take a quick diversion into the Swing library to see how Observer is used.

Images
Images

The Swing library

You probably already know that Swing is Java’s GUI toolkit for user interfaces. One of the most basic components of that toolkit is the JButton class. If you look up JButton’s superclass, AbstractButton, you’ll find that it has a lot of add/remove listener methods. These methods allow you to add and remove observers—or, as they are called in Swing, listeners—to listen for various types of events that occur on the Swing component. For instance, an ActionListener lets you “listen in” on any types of actions that might occur on a button, like a button press. You’ll find various types of listeners all over the Swing API.

A little life-changing application

Okay, our application is pretty simple. You’ve got a button that says “Should I do it?” and when you click on that button the listeners (observers) get to answer the question in any way they want. We’re implementing two such listeners, called the AngelListener and the DevilListener. Here’s how the application behaves:

Images

Coding the life-changing application

This life-changing application requires very little code. All we need to do is create a JButton object, add it to a JFrame and set up our listeners. We’re going to use inner classes for the listeners, which is a common technique in Swing programming. If you aren’t up on inner classes or Swing, you might want to review the “Getting GUI” chapter of Head First Java.

Images
Images
Images

That’s a good idea.

In our current Weather Station design, we are pushing all three pieces of data to the update() method in the displays, even if the displays don’t need all these values. That’s okay, but what if Weather-O-Rama adds another data value later, like wind speed? Then we’ll have to change all the update() methods in all the displays, even if most of them don’t need or want the wind speed data.

Now, whether we pull or push the data tot the Observer is an implementation detail, but in a lot of cases it makes sense to let Observers retrieve the data they need rather than passing more and more data to the Observers through the update() method. After all, over time, this is an area that may change and grow unwieldy. And, we know CEO Johnny Hurricane is going to want to expand the Weather Station and sell more displays, so let’s take another pass at the design and see if we can make it even easier to expand in the future.

Updating the Weather Station code to allow Observers to pull the data they need is a pretty straight forward exercise. All we need to do is make sure the Subject has getter methods for its data, and then change our Observers to use them to pull the data that’s appropriate for their needs. Let’s do that.

Meanwhile back at Weather-O-Rama

Images

There’s another way of handling the data in the Subject: we can rely on the Observers to pull it from the Subject as needed. Right now, when the Subject’s data changes, we push the new values for temperature, humidity, and pressure to the Observers, by passing that data in the call to update().

Let’s set things up so that when an Observer is notified of a change, it calls getter methods on the Subject to pull the values it needs.

To switch to using pull, we need to make a few small changes to our existing code.

For the Subject to send notifications...

  1. We’ll modify the notifyObservers() method in WeatherData to call the method update() in the Observers with no arguments:

Images

For an Observer to receive notifications...

  1. Then we’ll modify the Observer interface, changing the signature of the update() method so that it has no parameters:

    Images
  2. And finally, we modify each concrete Observer to change the signature of its respective update() methds and get the weather data from the Subject using the WeatherData’s getter methods. Here’s the new code for the CurrentConditionsDisplay class:

    Images

Code Magnets

Images

The ForecastDisplay class is all scrambled up on the fridge. Can you reconstruct the code snippets to make it work? Some of the curly braces fell on the floor and they were too small to pick up, so feel free to add as many of those as you need!

Images

Test Drive the new code

Images

Okay, you’ve got one more display to update, the Avg/Min/Max display, go ahead and do that now!

Just to be sure, let’s run the new code...

Images

Tools for your Design Toolbox

Images

Welcome to the end of Chapter 2. You’ve added a few new things to your OO toolbox...

Images

Design Principle Challenge

Images

For each design principle, describe how the Observer Pattern makes use of the principle.

Images

Design Patterns Crossword

Images

Time to give your right brain something to do again! All of the solution words are from Chapter 1 & Chapter 2.

Images

ACROSS

1. One Subject likes to talk to _______ observers.

3. Subject initially wanted to _________ all the data to Observer.

6. CEO almost forgot the ________ index display.

8. CurrentConditionsDisplay implements this interface.

9. Java framework with lots of Observers.

11. A Subject is similar to a __________.

12. Observers like to be ___________ when something new happens.

15. How to get yourself off the Observer list.

16. Ron was both an Observer and a _________.

18. Subject is an ______.

20. You want to keep your coupling ________.

21. Program to an __________ not an implementation.

22. Devil and Angel are _________ to the button.

DOWN

1. He didn’t want any more ints, so he removed himself.

2. Temperature, humidity and __________.

4. Weather-O-Rama’s CEO named after this kind of storm.

5. He says you should go for it.

7. The Subject doesn’t have to know much about the _____.

10. The WeatherData class __________ the Subject interface.

13. Don’t count on this for notification.

14. Observers are______ on the Subject.

17. Implement this method to get notified.

19. Jill got one of her own.

Design Principle Challenge Solution

Images
Images

Code Magnets Solution

Images

The ForecastDisplay class is all scrambled up on the fridge. Can you reconstruct the code snippets to make it work? Some of the curly braces fell on the floor and they were too small to pick up, so feel free to add as many of those as you need! Here’s our solution.

Images
Images

Design Patterns Crossword Solution

Images
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset