Design Pattern Example (Observer)

In this example, we have a series of historic stock prices and want to display them as a chart. The prices may be modified by the user in any order (we aren't just adding on to the end of the list). Consider this design: we could design a class PriceHistory and give it a "edit" method to change a value, an "add" method to add a new, most-recent price and a "draw" method that draws the chart on the screen. To make sure that the chart is always up-to-date, the add and edit methods would have to call the draw method when the data changes.

This design clearly will work. However, it doesn't promote reuse at all. First, if we want to also display the list as text, we have to create another method to output the text and the two output methods have to understand the dimensions of the screen to share it. Second, if we want to provide this same functionality with another series of data, the knowledge of the use of the screen has to be shared among both of the instances of the PriceHistory class.

The root of the problems in this design is that the PriceHistory class is representing both the internal and external representations of the data. It would be a cleaner design if there were two classes (PriceHistory and Chart), each dealing with one representation of the data. The problem is how to share the data between those classes. We do NOT want to duplicate the data (NEVER DUPLICATE DATA!), because then we have to worry about keeping the data synchronized. We also don't want the classes to be tightly coupled (define) as that would reduce reusability. Fortunately, there is a design pattern that fits this solution.

The intent of the Observer dsign pattern is to "define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically."

In this pattern, the "subject" owns the internal representation of the data. The "observers" subscribe to the subject and are therefore notified by the subject when the data changes. This is a design pattern because it is often wise to separate differents aspects of an abstraction.

Using this pattern for our PriceHistory problem has two large benefits:

  1. Outputting the data in new ways requires us to develop new observers, but we don't have to change existing observers or the subject.
  2. When the data is modified, we can update any number of observers about the change and each can react as it requires.
  3. If we want to output some other list of data as a chart, we can reuse the chart class completely (just create a new instance of it and have it subscribe to the new data class).

The structure of the Observer pattern we are applying is:

Participants

Collaborations

Note how the Observer object that initiates the change request postpones its update until it gets a notification from the subject. Notify is not always called by the subject. It can be called by an observer or by another kind of object entirely.