A Pattern Problem
July 6, 2001


The Problem

An application abstracts objects of type MortgageLoan.

A mortage loan comes in many flavors, e.g., fixed-rate, variable-rate, construction-loan, refinancing, second mortgage, etc. Part of the state and behavior of a mortgage loan object is common to all the flavors, but part of the state and behavior, e.g., the current interest and the estimated cost depend on a specific flavor.

This situation immediately suggests an architecture in which a base class (possibly abstract or an interface) has a hierarchy of subclasses. However, two requirements of the application are:

  1. A mortgage loan object refers (has pointers) to customers and/or builders objects which in turns refer to other other mortage loan objects and so on.
  2. Some mortgage loan objects can change flavor during the execution of the application, e.g., a construction-loan becomes a fixed-rate or variable-rate loan after 12 months of its starting date or at the completion of the construction, whichever come first.
A hierarchy of classes as outlined earlier wouldn't work. Why? An object cannot change class at run-time. For example, when a construction-loan object, say X, becomes a fixed-rate loan, X is discarded and a new object, say Y is created. The new object Y is fine, but all other objects that pointed to X should now point to Y and are therefore inconsistent.

The Bad Architecture

There is only one mortgage loan class, not a hierarchy. In each object of this class a variable records the specific flavor of the object. The mortgage loan class contains an implicit hierarchy of subclasses. The functionality common to all the implicit subclasses is coded and maintained without problems. The functionality specific to implicit subclasses is coded in the class itself and dispatched by a multibranch statement.

It is likely that many methods of the class will contain multibranch statements to dispatch flavor-specific functionality. Maintaining the implicit hierarchy is more difficult and error prone than with an explicit hierarchy. State variables specific to only one or a few implicit subclasses are shared by the entire class. This situation can lead to design and maintenance errors.

The Ugly Architecture

Each mortgage loan object has a list of Observers. The observers of an object X are objects that want to know when something interesting happens to X. In the application being discussed, an observer would be told that X has evolved into another object, say Y. Each observer could then update its pointer(s) from X to Y.

This architecture is flexible in the sense that it easily accomodates additions, removals and updates of the hierarchy of mortgage loan classes. However, it requires extra storage (for the lists of observers) and extra computations (to maintain references to mortgage loan objects consistent). This architecture is fairly complicated.

The Good Architecture

There is only one MortgageLoan class. This class only implements the functionality common to all the flavors of mortgage loans. There is a hierarchy of classes for the flavor-specific portion of a mortgage loans. The base class or interface of the classes in this hierarchy is called State. The MortgageLoan contains (a reference to) an object of type State called state. It also contains stub methods for all the methods of State. These methods delegate any computation to the corresponding methods of state - exactly as in the Proxy pattern.

This architecture accomodates additions, removals and updates of the hierarchy of mortgage loan classes as the Ugly Architecture. It requires no more memory and computation than the Bad Architecture. It is much easier to understand and maintain. This archicture is called a State Pattern. Objects implementing this architecture are called stateful objects.