Design Patterns and OOP Principles


Introduction

Design patterns are tried-and-true design solutions to recurring problems in software construction.  They  provide ways to structure software components into systems that are flexible, extensible, and have a high degree of reusability, an elusive goal in software engineering.  OO design patterns comes very close to achieving this goal by making effective use of polymorphism, striking a balance between inheritance and composition to build objects.  In this course, we focus only on OO design patterns.  So far, we have seen the following patterns.

We now go back to these patterns and discuss them in more details from the perspective of the following object-oriented programming principles (OOPP).


I. The Union Pattern

Suppose I am faced with the problem of computing the areas of geometrical shapes such as rectangles and circles.  OOPP #0 suggests that I build objects that are capable of computing these areas.  The variants for this problems are the infinitely many shapes: rectangles, circles, etc.  OOPP #1 drives me to define concrete classes such as Rectangle and Circle, and make them subclasses of an abstract class, called AShape, which has the abstract capability of computing its area.  This is an example of the simplest yet most fundamental OO design pattern called the Union Pattern.  It is the result of applying OOPP #0 and OOPP #1.

wpeE.gif (5556 bytes)

The Union Pattern is the result of partitioning the sets of objects in the problem domain into disjoint subsets and consists of

A client of the Union Pattern uses instances of the concrete subclasses (Variant1, Variant2), but should only see them as AClass objects.   The client class code should only concern itself with the public methods of AClass and should not need to check for the class type of the concrete instances it is working with.  Conditional statements to distinguish the various cases are gone resulting in reduced code complexity, making the code easier to maintain.

II. The Strategy Pattern

Going back to the Pizza problem, we see that the Pizza has a shape and delegates the computation of its area to its shape.  It does not care what the exact type of its shape is.  It only knows that its shape is capable of computing the appropriate area.    This is an example of what is called the Strategy Pattern.  The Pizza uses its shape as a "strategy" to compute its area.

wpeF.gif (6773 bytes)

In general, the strategy pattern consists of a union pattern of strategies, and a client class, called the context, that contains a reference to the abstract strategy in the union. The context delegates all works to this stategy reference.  In our Pizza example, the context is the Pizza class, and the abstract AShape plays the role of the (abstract) strategy.

III. The Composite Pattern

More that often, we combine (or compose) objects to form new objects.  Recursive composition, in particular, is a common object design.  AList is one such example.  The recusive object structural design gives rise to recursive algorithms on the object.  This design pattern is called the Composite Pattern.

wpe10.gif (7317 bytes)

In the above, classes Basic1 and Basic2 correspond to the base cases in the recursion, and Composite corresponds to the non-base cases.  The method operation () for Composite is mostly recursive. 

IV. The Singleton Pattern

Class EmptyList represents the "empty list".  Conceptually, there is only one empty list in this world.  The concept is akin to that of the empty set: there is only one empty set.  How can we ensure that only one instance of EmptyList can be created throughout the life of a program?  There is a way to design a class to ensure such uniqueness property.  It is called the Singleton Design Pattern.  The following UML diagram describe the pattern.

 

wpe1.gif (4966 bytes)

Note: The field _instance and the method UniqueInstance () are of class scope (i.e. static).

The method UniqueInstance () is called a "factory" method as it is used to manufacture an instance, though unique, of the SingletonClass.   The class SingletonClass is appropriately called a "factory".   In this very special case, SingletonClass manufactures its own (unique) instance.  We will revisit the "factory pattern" in future lectures.

In Java, the singleton pattern can be implemented as shown in the following UML diagram.

singleton.png (2834 bytes)

dxnguyen@cs.rice.edu
Copyright 2000, Dung X. Nguyen - All rights reserved.