Observer Pattern

Starting Point Analysis

In the Project Risk Analysis, I know that if I can develop a spreadsheet that can be access by a single user with multiple views, then I can use Pyro and my method to extend it to a distributed, multi-user spreadsheet. So I don't need to consider any network communication in my early phases of development. So developing a non-distributed, single-user spreadsheet is my present concern. This spreadsheet should support all the requirements except the distributed and multi-user requirement. Even for this simplified requirment, I use several phases for development.

Requirement in this phase

In this phase, the following requirment should be fulfilled:
  1. Implement a spreadsheet class that store all cell values.
  2. Implement a plot view class that can plot any part of the spreadsheet.
  3. Implement a spreadsheet view class that can show any part of the spreadsheet.
  4. Implement a text interface that allows user to select any parts of the spreadsheet for plot or spreadsheet viewing.
  5. In this text interface, a user can change a cell's value (only numeric). When the spreadsheet is updated, all the view instance should also updated.

Observer Pattern Overview

The following simple description of observer pattern is from the book, Design Patterns. Please see page 293-299 of this book for more details.

  1. Intent

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

  2. Structure

  3. Participants

    1. Subject
      1. knows its observers. Any number of Observer objects may observe a subject.
      2. provides an interface for attaching and detaching Observer objects.
    2. Observer
      1. defines an updating interface for objects that should be notified of changes in a subject.
    3. ConcreteSubject
      1. stores state of interest to ConcreteObserver objects.
      2. sends a notification to its observers when its state changes.
    4. ConcreteObserver
      1. maintains a reference to a ConcreteSubject object.
      2. stores state that should stay consistent with the subject's.
      3. implements the Observer updating interface to keep its state consistent with the subject's.
  4. Collaborations

UML Design in this phase

In our project, we have a spreadsheet which should be observed by the different views. When the state of the spreadsheet is changed, all the views are updated. So, the observer pattern is quit suitable for this purpose. Based on this pattern, I design the first class diagram in UML, which is shown in the following diagram.

Steps in this phase

  1. prototype 1

    In this prototype, we build a simplest version. No Gui observer, no spreadsheet subject, no text interface for changing the state of subject. But the frame of observer pattern is there. It consists of:

    1. subject class: containing only one single Data object.
    2. plotobserver and spreadsheetobserver classes: simply print the changed value of data on the screen.
    3. data class: implements the corresponding class in UML class diagram.
    Since there is no interface for editing the subject. I simply use the python interactive interface to instantiate class objects and change the state of subject. The source code can be found here. The running result could look like this.
  2. prototype 2

    In prototype 1, the spreadsheet class is added so that a spreadsheetsubject instance can have a single spreadsheet instance. The spreadsheet class is also an aggregate of Data objects. With slight modification of spreadsheetsubject class, we can have our prototype 2. Run it as prototype 1, we can get the same result.

  3. prototype 3

    In this prototype, we build our own simple text-interface. To run source code, simple issue the command: python txtinterface.py. The running result would look like this.

  4. prototype 4

    In this prototype, we change the spreadsheetobserver into a real spreadsheeetobserver. In this real spreadsheetobserver, user can specify any part of the spreadsheet to plot as long as it is in the range of the spreadsheet which is referenced by the spreadsheetsubject. With a slight modification of txtinterface.py. the runing result of source code would be like this.

  5. prototype 5

    In this prototype, we change the plotobserver into a real plotobserver. In this real plotobserver, user can specify any one column, one row, or two consecutive column or rows for plotting. With a slight modification of txtinterface.py. the runing result of source code would be like this.

  6. prototype 6

    In this prototype, we build a more powerful text interface. As you may noticed in the source code, the setState() of spreadsheetsubject and spreadsheet classes are also changed to that stated in UML class diagram.

References

Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Design Patterns Elements of Reusable Object-Oriented Software Addison-Wesley, 1995