; patterns
Learning Center
Plans & pricing Sign in
Sign Out



Programming Tutorials for java,data structure,core-java,advance java,thread

More Info
  • pg 1
									                        Teaching Data Structure Design Patterns
                      Natasha Gelfand∗         Michael T. Goodrich†        Roberto Tamassia∗
                    Dept. of Comp. Sci.        Dept. of Comp. Sci.        Dept. of Comp. Sci.
                        Brown Univ.            Johns Hopkins Univ.            Brown Univ.
                    Providence, RI 02912       Baltimore, MD 21218        Providence, RI 02912
                     ng@cs.brown.edu          goodrich@cs.jhu.edu          rt@cs.brown.edu

Abstract In this paper we present an approach               of data structures. The design patterns we discuss in-
for teaching the Freshman-Sophomore introduction            clude the following: adapters, template method, com-
to data structures course (CS2) in a way that pro-          parators, decorators, iterators and enumerations, po-
vides an introduction to object-oriented software en-       sitions, and locators. Incorporating these patterns
gineering patterns in addition to the theory of data        doesn’t require any major revisions to the CS2 cur-
structures. We survey in this paper several design          riculum, for, as we describe below, they fit in nat-
patterns and describe how they can be naturally in-         urally with the discussions of several components of
tegrated in the CS2 curriculum.                             CS2. These patterns apply to a course taught in any
                                                            object-oriented language, we will give our examples
1    Introduction                                           in Java.

One of the main advantages of object-oriented de-           Related Work Software engineers have used de-
sign is to encourage well-organized code development        sign paradigms, or patterns, for some time now. Even
for building software that is reusable, robust, and         so, it wasn’t until the recent, yet seminal, cata-
adaptable (e.g., see [2,3,6]). Designing quality object-    loging effort of the so-called “gang of four,” Gamma
oriented code takes more than simply understanding          et al. [4], that the subject of design patterns be-
the object-oriented design methodologies, however.          came a topic of study in its own right. The ef-
It requires the effective use of these and other object-     forts of these four, and other software engineering re-
oriented techniques in powerful and elegant ways.           searchers, have shown that design patterns can save
                                                            development time and result in software that is ro-
Design Patterns Software engineering researchers            bust and reusable.
and practitioners are developing sets of organiza-              At Brown University design patterns have been
tional concepts for designing quality object-oriented       taught as early as the introductory computer sci-
software. These concepts, called design patterns [4],       ence course (CS1) [7]. The patterns presented in-
are frameworks that one might follow for producing          cluded state, proxy, chain of responsibility, and fac-
object-oriented software that is concise, correct, and      tory. Most of the patterns we describe in this pa-
reusable. Such patterns are important, but probably         per are also described in the book by Gamma et
neglected by most instructors in the introduction to        al., including adapters, iterators, template methods,
data structures course (CS2) and usually not taught         and decorators. Other patterns we describe here, in-
until the software engineering course. We briefly sur-       cluding positions, locators, and comparators, and the
vey several object-oriented design paradigms in this        way that they can be integrated in the CS2 curricu-
paper, and describe how these paradigms can be con-         lum, are included in the recent book by Goodrich and
sistently integrated into the curriculum of CS2, teach-     Tamassia [5].
ing students how to design quality implementations              In the remainder of this paper we describe these
  ∗ The work of this author is supported by the U.S. Army
                                                            patterns and how they can naturally be included in
Research Office under grant DAAH04–96–1–0013, and by the      the CS2 curriculum. We break the patterns into two
National Science Foundation under grant CCR–9423847.
  † The work of this author is supported by the U.S. Army   groups: those that primarily act on classes and those
Research Office under grant DAAH04–96–1–0013, and by the      that primarily act on objects.
National Science Foundation under grant CCR–9625289.

                                                            2   Class Patterns
                                                            Many patterns act on classes. That is, they provide
                                                            extra capabilities for a class of objects, which the
                                                            designer of that class need not be directly aware of.
                                                            We describe some of these patterns in this section.
Adapter The adapter pattern adjusts methods                adapter, for example, to define an IntegerArrayStack
from one class so they can be used to implement            class that adapts an array-based ArrayStack class so
methods of another class. The adaptation is expected       that the stack only stores Integer objects. Such a
to be a simple one, involving what are essentially one-    class can then be used to to avoid the extra typing
line method calls to implement each method. This           and possible confusion associated with casting.
sometimes also involves not using several of the meth-
ods from a more general class. This adaptation is          Template Method Often several algorithms have
commonly done in design of data structures when we         the same overall structure but differ in the actions
want to implement a new data structure in terms of         they take at specific steps. For example, many al-
another data structure that has a similar functional-      gorithms have as a base a simple tree traversal, but
ity, but different interface. A natural place to intro-     differ in the actions they perform at the nodes of a
duce this pattern is in the discussion of implementa-      tree. In such cases it is desirable to implement the
tion of stacks, queues, and double-ended queues (or        algorithm only once and then specialize it for the dif-
deques).                                                   ferent applications.
    The adapter pattern can naturally be included              The design pattern that can be used in such situa-
early in the CS2 curriculum, in the implementation         tions is called template method. This pattern provides
of DequeStack class shown in Code Fragment 1. This         a class which implements a skeleton of an algorithm,
class demonstrates how to adapt a deque class so that      and delegates the steps that will vary in different im-
it can be used to implement the stack abstract data        plementations to its subclasses.
type (ADT). That is, if we have an implementation              Template methods can be introduced in CS2 dur-
MyDeque of the deque ADT, then we can easily im-           ing the discussion of tree and graph traversals. We
plement the Stack interface with the class DequeStack      can generalize different tree traversals, such as pre-
shown in Code Fragment 1. All the methods of De-           order and postorder visit, to one generic visit of the
queStack are essentially one-line calls to methods of      tree, called Euler tour, where we start by going from
the Deque interface, with the slight added complica-       the root towards the left child viewing the edges of
tion of converting deque exceptions into stack excep-      the tree as being walls that we always keep to our
tions.                                                     left. Each node, therefore, will be encountered three
                                                           times by the Euler tour: from the left, from below,
public class DequeStack implements Stack {                 and from the right. Since all algorithms using an Eu-
  Deque D; // holds the elements of the stack              ler tour will have the same general structure, we can
  public DequeStack() { D = new MyDeque(); }               define an abstract class BinaryTreeTraversal, shown
  public int size() { return D.size(); }                   in Code Fragment 2, which executes the traversal, but
  public boolean isEmpty() { return D.isEmpty(); }
                                                           does not take any specific action when it encounters
  public void push(Object obj) { D.insertLast(obj); }
                                                           a node. Instead, it calls auxiliary methods which are
  public Object top() throws StackEmptyException {
    try { return D.lastElement(); }                        left empty in the abstract class, but are defined in the
    catch (DequeEmptyException err)                        subclasses of the traversal to perform some actions.
        { throw new StackEmptyException(); }               For example, we can produce preorder and postorder
  }                                                        traversals of the tree by performing an action when a
  public Object pop() throws StackEmptyException {         node is encountered from the left and from the right
    try { return D.removeLast(); }                         respectively.
    catch (DequeEmptyException err)                            An alternative approach to the problem of gen-
        { throw new StackEmptyException(); }               eralized algorithms is to defer the specific actions to
  }                                                        separate objects instead of the subclasses of the ab-
                                                           stract class and use the strategy pattern [4] instead
Code Fragment 1: Implementation of the Stack inter-        of the template method pattern.
face by means of a deque.                                  Comparator Another useful pattern that acts
    Another useful application of the adapter pattern      upon a class is the comparator pattern, which is an
in design of data structures is to specialize the types    instance of a more general strategy pattern. This pat-
of objects that are used by a general class. This allows   tern provides a class of objects that are used for com-
us to design general data structures which can store       paring pairs of objects in a totally-ordered container.
objects of any type. We can then make the data             An alternative approach is to require that objects be
structure type-safe by writing an adapter that only        able to compare themselves to one another, but there
accepts objects of a certain type and then forward         are contexts in which this solution is not applicable.
all calls to the generic class. We can use this kind of    Often objects do not need to “know” how they ought
public abstract class BinaryTreeTraversal {              public class Lexicographic implements Comparator {
   public void traverseNode(Position p) {                  // Assumes Point2D objects have getX() and
        left(p);                                           // getY() methods for coordinates.
        traverseNode(tree.leftChild(p));                   public boolean isLess(Point2D a, Point2D b) {
        below(p);                                            if (a.getX() == b.getX())
        traverseNode(tree.rightChild(p));                        return (a.getY() < b.getY());
        right(p);                                            return (a.getX() < b.getX());
   }                                                       }
   // specific actions to take will be defined here          // other methods are implemented in a similar fashion
   protected void left(Position p) {}                    }
   protected void below(Position p) {}
   protected void right(Position p) {}                   Code Fragment 3: An implementation of the Compara-
}                                                        tor interface for 2-dimensional points.

Code Fragment 2: Generalized Euler tour of a binary      need to have such variables.
                                                         public interface Decorable {
to be compared, or there may be multiple compari-           public void create (Object key, Object value);
son methods that will add unnecessary complexity to         public Object destroy(Object key);
the interface of those objects. For example, for two-       public boolean has(Object key);
dimensional data, it is not clear whether we should         public void set (Object key, Object value);
                                                            public Object get(Object key);
use the first coordinate or the second as the primary
                                                            public Enumeration attributes();
comparison value (or some other rule altogether). In-
deed, there are several contexts in geometric algo-
rithms where we might want to dynamically switch         Code Fragment 4: An interface for objects that support
between different comparison functions. Thus, the         adding decorations. Here key is a reference to the new
data structures that need to compare objects should      decoration.
not expect the objects to provide their own compar-
ison rules, but instead delegate this task to a com-     if (v.get(VISITED) == Boolean.FALSE) {
parator object.                                              v.set(VISITED, Boolean.TRUE);
    Comparators are most naturally introduced in             visit(v);
CS2 during the discussion of comparison-based data       }
structures, such as priority queues and dictionaries.
                                                         Code Fragment 5: An example of vertex visit in depth-
For example, a priority queue Q that is designed with    first search using a decoration to store whether the vertex
comparators in mind is initialized with a given com-     has been explored.
parator, which is then used by Q to compare two
objects. We can even imagine the ability for a pri-          Decorators can be introduced in the CS2 curricu-
ority queue to be given a new comparator if the old      lum in the discussion of balanced binary search trees
one even becomes “out-of date”. Thus, a program-         and graph algorithms. In implementing balanced bi-
mer can write a general priority queue implementa-       nary search trees we can use a binary search tree class
tion that can work correctly in a wide variety of con-   to implement a balanced tree. However, the nodes of
texts (including some the programmer has probably        a binary search tree will have to store extra informa-
not even thought about). Formally, a comparator in-      tion such as a balance factor (for AVL trees) or a color
terface provides methods, isLess, isLessOrEqual, areE-   bit (for red-black trees). Since the nodes of a generic
qual, isGreater, and isGreaterOrEqual. We provide an     binary search tree do not have such variables, they
example implementation of the Comparator interface       can be provided in the form of decorations. In the
in Code Fragment 3.                                      implementation of graph traversal algorithms, such
                                                         as depth-first search and breadth-first search, we can
Decorator The final class pattern we discuss in           use the decorator pattern to store temporary infor-
this section is the decorator pattern. This pattern is   mation about whether a certain vertex of a graph has
used to add extra attributes or “decorations” to ob-     been visited (see Code Fragment 5). The decorator
jects with a certain interface (one possible interface   pattern can be used in conjunction with the position
is shown in Code Fragment 4). The use of decora-         pattern described in Section 3.
tors is motivated by the need of some algorithms and
data structures to add extra variables or temporary
scratch data to the objects that will not normally
3    Object Patterns                                      malizes the intuitive notion of “place” of an element
Other patterns act primarily on objects. We describe      in a collection. A collection, then, stores its elements
some of them in this section.                             in positions and keeps the positions arranged in some
                                                          specific order. The Position interface provides meth-
Iterator Often we are interested in accessing the el-     ods for accessing the element stored at that position
ements of a collection in certain order, one at a time,   and the collection that the position belongs to.
without changing the contents of the collection, e.g.         Some examples of positions are nodes in such data
to look for a specific element or to sum the values        structures as sequences and trees. Usually, the nodes
of all its elements. An iterator is an object-oriented    are a part of the implementation of these data struc-
design pattern that abstracts the process of scanning     tures and therefore are not visible to the user. In an
through a collection of elements, one element at a        array-based implementations of sequences, there are
time, without exposing the underlying implementa-         no nodes, so positions are represented by the array
tion of the collection. A typical interface of an it-     indices. The position pattern provides a uniform in-
erator will include methods isDone(), firstElement(),      terface for different implementations of positions in
nextElement(), and currentElement(). This ADT al-         various data structures and makes the positions part
lows us to visit each element in a collection in order,   of the interface of a data structure. For example, we
keeping track of the “current” element.                   can provide a method insertAfter(Position p, Object el-
    Iterators can be discussed in the CS2 curriculum      ement) in the interface of a sequence that allows us to
as soon as elementary data structures introduced.         insert a new element into the sequence immediately
Java provides the simplified “streamlined” version of      after a given position (node).
the iterator pattern in its Enumeration interface. Any        A big advantage of being able to refer to individ-
time several objects need to be examined by some          ual positions is that it allows us to perform several
class, they can be given to that class in an enumer-      operations on collections more efficiently. For exam-
ation. It is often useful to be able to run through       ple, given an implementation of a doubly linked list
or enumerate all the objects in a particular collec-      with nodes that have next and prev pointers, we can
tion, so it can be useful to require all collections to   insert an arbitrary node v in O(1) time, provided we
support a method for returning their elements in an       are given a reference to the node preceding (or follow-
enumeration. Some collections, such as trees, are not     ing) v. We can just “link in” the node new by updat-
linearly ordered, and there may be several different       ing its next and prev references, as well as those of
ways to enumerate their elements (e.g. preorder and       its neighbors. Some possible places in the CS2 where
postorder traversal). Using enumerations to traverse      positions can be introduced include the discussions of
collections does not require knowledge of the internal    sequences and binary trees, where positions abstract
details of how the collection is implemented. For ex-     the concept of nodes, and discussion of graphs where
ample, one may wish to write a generic printCollection    positions represent vertices and edges. Positions can
method, shown in Code Fragment 6, that can print          be used in conjunction with the decorator pattern
out the contents of a collection of objects.              discussed in Section 2, since positions are the objects
                                                          to which decorations can be added (in fact Position
public printCollection(Collection c) {                    interface can extend Decorable). Not all data struc-
   Enumeration enum = c.elements();                       tures support a natural notion of position, however,
   while (enum.hasMoreElements()) {                       and for those structures we can use the pattern we
                                                          discuss next.
}                                                         Locator The Position interface, described above,
                                                          allows us to identify a specific “place” that can
Code Fragment 6: An example of using an enumera-
                                                          store an element. The element at some position
                                                          can change, but the position stays the same. How-
    When it is created, an Iterator or Enumeration ob-    ever, just having positions is not enough. When dis-
ject may or may not be a “snapshot” of the collection     cussing in CS2 priority queues, dictionaries, and (in a
at that time, so it is not a good idea to use iterator    fast-paced course) Dijkstra’s shortest path algorithm,
objects while modifying the contents of a collection.     there are applications where one needs to keep track
Position In order to abstract and unify the differ-        of elements as they are being moved from position to
ent mechanisms for storing elements in various im-        position inside a collection. In order to keep track of
plementations of data structures, we introduce the        the location of each such object in an object-oriented
concept of position in the data structure, which for-     manner, we need an abstraction of “location” that fol-
lows an element around, rather than being associated      second fragment shows the relaxation of edge (u, z),
with a fixed position. This need is particularly impor-    and the update of the priority of vertex z in Q, which
tant for data structures where there is no real concept   is performed with operation replaceKey.
of “positions” in the structure (e.g., key-based struc-
tures). A simple design pattern that fulfills this need    Locator u loc = Q.insert(new Integer(u dist), u);
                                                          setLocator(u, u loc);
is the locator.
     The Locator interface is a simple ADT that ab-
                                                          if ( u dist + e weight < z dist ) // relaxation
stracts the location of a specific element in a collec-         Q.replaceKey(z loc, new Integer(u dist + e weight));
tion. A locator “sticks” with its associated element
as long as that element remains in the collection,        Code Fragment 7: Fragments from the implementation
i.e., a locator remains valid until its associated ele-   of Dijkstra’s algorithm
ment is removed or replaced. Like the Position ADT,
the Locator ADT supports a method for returning           4    Conclusion
its element. Even though they both support such a         In this paper we survey a number of useful object-
method, the Locator and Position interfaces are ac-       oriented software design patterns and describe natu-
tually complements of each other: a Locator object        ral places where they can be introduced in the stan-
stays with a specific element, even if it changes from     dard curriculum for the Freshman-Sophomore data
position to position, and a Position object stays with    structures course (CS2). We summarize our sugges-
a specific position, even if it changes the elements it    tions in Table 1. We feel that introducing such design
holds. A locator, therefore, is like a coat check: we     principles early in the computer science curriculum
can give our coat to a coat room attendant, and we        helps students form a framework for engineering soft-
receive back a coat check, which is a “locator” for       ware that will complement the theoretical foundation
our coat. The position of our coat relative to the        they receive in CS2.
other coats can change, as other coats are added and
removed, but our coat check can always be used to          Design Pattern                    CS2 Topic
retrieve our coat. Like a coat check, then, we can             adapters                  stacks and queues
now imagine getting something back when we insert          template methods          tree and graph traversals
an element into a collection: we can get back a loca-        comparators                   priority queues
tor to that element. This in turn can then be used to         decorators               balanced trees, graphs
provide quick access to the position of this element in        iterators              sequences, trees, graphs
the collection to, say, remove this element or replace         positions          sequences, binary trees, graphs
it with another element.                                       locators             priority queues, dictionaries
     We can use locators in a very natural way in
the context of a priority queue. A locator in such        Table 1: Some design patterns and natural places in the
a scenario stays attached to an element inserted in       CS2 curriculum where they can be introduced.
the priority queue and allows us to refer to the ele-
ment and its key in a generic manner that is indepen-
dent from the specific implementation of the priority
queue. This ability is important for a priority queue     [1] A. V. Aho, J. E. Hopcroft, and J. D. Ullman. Data
implementation, for there are no positions per se in          Structures and Algorithms. Addison-Wesley, 1983.
a priority queue, since we do not refer to elements or    [2] G. Booch. Object-Oriented Analysis and Design with
keys by any notions of “rank,” “index,” or “node.”            Applications. Benjamin/Cummings, 1994.
By using locators, we can define methods for a prior-      [3] T. Budd. An Introduction to Object-Oriented Pro-
ity queue Q that refer to elements stored in Q in a way       gramming. Addison-Wesley, 1991.
that abstracts from the specific implementation of Q.      [4] E. Gamma, R. Helm, R. Johnson, and J. Vlis-
Such methods include remove( ), which removes the             sides. Design Patterns: Elements of Reusable Object-
element with locator , and replaceKey( , k), which            Oriented Software. Addison-Wesley, 1995.
changes to k the priority of the element with loca-       [5] M. T. Goodrich and R. Tamassia. Data Structures
tor . For example, Code Fragment 7, shows two                 and Algorithms in Java. John Wiley and Sons, 1998.
fragments from an implementation of Dijkstra’s al-        [6] B. Liskov and J. Guttag. Abstraction and Specification
gorithm in Java. The first fragment inserts a vertex           in Program Development. The MIT Press/McGraw-
u into a priority queue Q, using u’s distance as its          Hill, 1986.
key, and associates with u the locator returned by Q      [7] Computer Science 15 Homepage, Brown University.
(e.g., storing the locator as a decoration of u). The         http://www.cs.brown.edu/courses/cs015

To top