TOC PREV NEXT INDEX

Put your logo here!

The Essence of Object Oriented Programming with Java and UML


Chapter 7

Design Patterns

 

Design patterns have become an essential part of object-oriented design and programming. They provide elegant and maintainable solutions to commonly encountered programming problems. Before the mid-1990's, design patterns were seldom mentioned. Now it is difficult to find a current article or book about designing software that doesn't mention design patterns, and an understanding of design patterns has become a critical part of any object-oriented programmer's toolbox.

One of the key events in the spread of design patterns was the publication and popular acceptance of the book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (often called the Gang of Four or just GoF). Currently, design patterns are used mostly for software architecture and design, but the concept of patterns is moving to other areas of software development as well.

The goal of this chapter is to give you a good feeling for what design patterns are, and why they can lead to better designed object-oriented programs. You will need to read one of the design pattern books listed in Resources on page 223 for more complete coverage of design patterns.

What are Design Patterns?

One big challenge in developing software is avoiding reinventing the wheel. Using libraries and frameworks is one way to reuse useful tools for many software systems. The tools provided by libraries and frameworks solve common, but low-level problems.

Design patterns deal with solving common design problems at a higher level. They do not provide code that can be used directly for a specific problem, but rather a design solution to a software problem that has been found to come up repeatedly over many software projects. A design pattern provides a description of a design solution that can be adapted and applied to a specific situation.

The Gang of Four (GoF) Design Patterns book describes twenty-three patterns arranged into three groups. The groups help classify how the patterns are used. Creational patterns are used to help make a system independent of how the objects it uses are created. Structural patterns are concerned with how classes and objects are organized and composed to build larger structures. Behavioral patterns are used to deal with assignment of responsibilities to objects and communication between objects.

Using Design Patterns

The complexity of different design patterns ranges from simple to hard. For example, the Iterator design pattern is so simple and basic that it has become an essential feature of the standard Java object collections library. Others, such as the Composite pattern, are somewhat more complex, and require more experience to recognize when they are useful.

Most of the patterns are not inherently difficult or complex. In fact, good software designers have been using the solutions described by the patterns for years, but without formally recognizing that they really could be described as general design guidelines. One of the goals of developing design patterns has been to pass on the experience and knowledge of pattern authors to other programmers to help them produce better designs.

Using design patterns takes some experience. You must have at least a basic understanding of all the patterns available, and then be able to recognize when you have a design situation that can be helped by using a pattern. Often, this will require nothing more than reading through the patterns to see if any fit the case at hand. When a pattern fits, it tends to ring a little bell of recognition. The longer you work with patterns, the easier they become to use.

For the rest of this chapter, we will cover how design patterns are described in the GoF book, go over each of the basic GoF patterns, and finally show how a few patterns have been used in the Wmvc framework and the MovieCat application.

Design Pattern Description Template

The GoF developed a description template that is used in their book to define their patterns. The GoF template has also been adopted for descriptions of patterns found in other sources. The following table covers the sections included in the GoF pattern description template. Each pattern in the GoF book is defined using this layout.

Section
Description
Pattern Name and Classification
The name of the pattern, and its classification (Creational, Structural, or Behavioral).
Intent
A short statement about what the pattern does.
Also Known As
Alternate well known names for the pattern.
Motivation
An illustrative design problem that shows how the pattern can solve the problem.
Applicability
Situations where the pattern can be used.
Structure
A graphical (UML) representation showing the classes in the pattern.
Participants
The classes that participate in the pattern and their responsibilities.
Collaborations
How the participants collaborate.
Consequences
Benefits and trade-offs of using the pattern.
Implementation
Hints, pitfalls, and techniques that can be used to help implement the pattern.
Sample Code
Code illustrations of using the pattern.
Known Uses
Examples of the pattern used in real systems.
Related Patterns
Other patterns closely related to the current one.

The Gang of Four Patterns

The Design Patterns book presents descriptions of twenty-three different patterns. Since it was first published, other software designers have developed and defined new patterns. See Resources on page 223 for a list of some other pattern resources. However, the GoF Design Patterns remains the standard reference, and this section presents a brief description of the GoF patterns. The last section presents an example of how patterns can be used in the design of a real software system, in this case, Wmvc and MovieCat.

Creational Patterns

Abstract Factory

An Abstract Factory is a class that is used to create instances of other objects that are related to or depend on each other. An example of this is creating GUI components for different GUI toolkits. The Abstract Factory will let the application see a unified component, while it creates the appropriate concrete object for a given look-and-feel.

Builder

The Builder pattern is used by a Director class to construct different complex objects based on a specific requirement. An example is creating a text converter object that can convert text to different formats depending on how the converter is built.

Factory Method

A Factory Method provides a common interface for creating subclasses. The factory method is defined in the top level class definition, but instantiation of the subclasses determine which specific instance of the factory method is used.

Prototype

The Prototype pattern can reduce the number of different classes used by creating new object instances based on a copy or clone of an original prototype instance. The copies can then be modified to carry out their different responsibilities.

Singleton

Often there will be situations where there needs to be one and only one instance of a class. Rather than relying on the programmer to create only one instance of a class, the Singleton pattern will create only one instance of a class, and makes that instance accessible by other objects.

Structural Patterns

Adapter

The Adapter pattern is used to adapt an interface of one class so that it can be used by a different class that originally could not use it. The adapter is sometimes called a wrapper. For example, adapters or wrappers are often written for existing libraries so that a new application can use the library.

Bridge

A Bridge is used to decouple an abstraction from its implementation. The Bridge pattern is often used to build drivers, such as a printer driver, which connect an application program with a real printer. It is possible to vary the abstraction and the implementation independently.

Composite

The Composite pattern is used to compose whole-part hierarchies into a tree structure that will let the client treat either the individually objects, or compositions of those objects uniformly. An example is a graphical object, which can be made up of individual graphics (like a line or a square), or other graphical objects (a picture in a picture).

Decorator

The goal of the Decorator pattern is to add more responsibilities to an object dynamically, and avoid subclassing. An example is adding scrolling to a text view. The scrolling object surrounds the text view, handles the mechanics of the scroll bar, and then tells the text view to display itself appropriately.

Facade

The Facade pattern provides a higher level unified interface to a set of objects in a subsystem. The extra layer provides a simpler interface to the subsystem, and helps to avoid coupling between classes.

Flyweight

The Flyweight pattern is used to efficiently use a large number of small objects with sharing. An example is sharing representation of individual characters in a document formatting program.

Proxy

The Proxy pattern is similar to the Adapter in that it provides an interface layer between objects. While an Adapter will change the interface, a Proxy doesn't change the interface, but instead will control the access to one object from another.

Behavioral Patterns

Chain of Responsibility

The Chain of Responsibility pattern allows a sender to issue a request to a series or chain of objects and allowing each object a chance to handle the request. The receiving objects pass the request along until some object handles the request. An example is a context sensitive help system that will pass a request for help along a chain until the appropriate object can provide the help.

Command

The Command pattern provides a way to encapsulate a command request as an object without the object that issues the command needing to know what the response will be. An example is a GUI menu system that will issue a command in response to a menu selection. Any menu command can issue a request to a Command object in a uniform way without having to know how the object will handle the command.

Interpreter

The Interpreter pattern recognizes that sometimes it is better to define a language with a grammar, and to provide an interpreter for that language. An object that can recognize and respond to a regular expression search pattern is an example that can use the Interpreter pattern.

Iterator

The Iterator pattern is used to provide a means to access all the elements of some collection of objects sequentially without exposing the collection's internal representation. The Iterator is so common and useful that Java provides iterators for its collection objects as a standard feature.

Mediator

The Mediator pattern is used to define an object that knows how to use several other objects, and to provide a means for those objects to refer to each other using the Mediator instead of directly. This increases encapsulation and decreases coupling.

Memento

The Memento pattern is used to capture and save the current state of an object without violating its encapsulation. For example, an editor program would use the Memento pattern to save the state of whatever was being edited so that it could be restored via an undo command.

Observer

The Observer pattern is used when any number of objects (the Observers) need to be notified automatically whenever another object (the Observable) changes its state.

State

The State pattern is used to allow an object to change its behavior depending on how its internal state is changed. An example is a network monitoring object that will change its behavior depending on whether the network connection is open or closed.

Strategy

The Strategy pattern is used to define a family of interchangeable algorithms. The client will be able to use the object that implements the Strategy without necessarily knowing which strategy is used, or how it differs from other strategies. An example might be a Strategy that implements different sort algorithms, with each algorithm appropriate for different kinds of data.

Template Method

The Template Method is used to define an operation as a superclass whose implementation will be deferred to subclasses. This lets the subclasses redefine an operation without affecting how the method is used.

Visitor

The Visitor pattern is used to perform an operation on some structure of objects. The Visitor allows new operations to be defined without changing any of the elements that are part of the structure. An example would be visiting each leaf of a tree of objects to perform some operation.

Example Design Patterns used by Wmvc and MovieCat

Because design patterns can be so useful, it should be no surprise that several design patterns can show up in even small applications. The Wmvc framework and the MovieCat applications that we covered in Chapter 5 and 6 use several patterns. We will discuss some of the details of using the patterns in this section.

MVC

The GoF Design Patterns doesn't call Model/View/Controller a design pattern. Instead, it uses MVC as a higher level design that can be implemented using patterns. However, in other sources, MVC itself is called a design pattern.

Since we've covered MVC is some detail already, we won't cover it again here. However, we will look at how the Wmvc framework uses two of the GoF design patterns for its implementation.

Observer Pattern

The Observer pattern is an easy way to implement having the model update all the views when it changes state. Wmvc uses the Observer pattern for its implementation. To better understand Observer, we will start with an excerpted version of the full pattern description from Design Patterns. This fairly complete excerpt should help give you a good idea of what a pattern description is like. [Comments about text we've omitted from the full pattern description are shown in square brackets like this.]

Pattern

Observer, an Object Behavioral pattern

Intent

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

Also Known As

Dependents, Publish-Subscribe

Motivation

A common side effect of partitioning a system into a collection of cooperating classes is the need to maintain consistency between related objects. You don't want to achieve consistency by making the classes tightly coupled, because that reduces their reusability.

[A description of a GUI toolkit.]

The Observer pattern describes how to establish these relationships. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in state. In response, each observer will query the subject to synchronize its state with the subject's state.

Applicability

Use the Observer pattern in any of the following situations:

Structure

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

ConcreteSubject notifies its observers whenever a change occurs that could make it observers' state inconsistent with its own.

After being informed of a change in the concrete subject, a ConcreteObserver object may query the subject for information. ConcreteObserver uses this information to reconcile its state with that of the subject.

[Sequence diagram shown in original.]

Consequences

The Observer pattern lets you vary subjects and observers independently. You can reuse subjects without reusing their observers, and vice versa. It lets you add observers without modifying the subject or other observers.

[A discussion of further benefits and liabilities of the Observer pattern.]

Implementation

[A discussion of issues related to the implementation of the pattern. Since Observer is already provided by the Java library, the implementation details are not relevant.]

Sample Code

[An example of implementing the Observer pattern.]

Known Uses

The first and perhaps best-known example of the Observer pattern appears in Smalltalk Model/View/Controller (MVC), the user interface in the Smalltalk environment. MVC's Model class plays the role of Subject, while View is the base class for observers. [more examples given.]

Related Patterns

[Two patterns related to the example are given.]

Observer Pattern in Wmvc

We know that from reading Design Patterns that Observer is useful for MVC. How is Observer really used by Wmvc?

It turns out that Wmvc can simply use the Observer supplied by the Java library, and won't have to implement it. The descriptions in Design Patterns include a discussion for implementation of a pattern, but in this case, that's already done. We just need to figure out how to use Observer to implement MVC.

First, let's look at the specifics of the Java Observer implementation. It defines a class called Observable that corresponds directly to the Subject class in the pattern description. It also provides the Observer interface, which corresponds to the Observer class in the pattern. This makes sense. Since an Observer only needs one method, update, an interface works well for this, and it allows the different observers to be derived from other classes. The Observable (Subject) needs to provide several services to implement the pattern. The Java Observable class has named the Subject attach method addObserver, and the Subject detach method deleteObserver. The Subject notify is named notifyObservers. There are some other methods provided to make using Observable easier. Figure 7-1 shows the relevant details in UML.

Figure 7-1.
Java Observer

Now we are ready to see how Wmvc uses Observable. In MVC, what is the Subject, or Observable? It is the Model. So, we will extend Observable in WmvcModel. And the observers are the Views, so we will implement Observer in WmvcView. To stay consistent with the MVC model, we will provide the functionality of the xObservable methods renamed as xView methods instead (e.g., addView instead of addObserver). While it can be good to use the names described in a pattern, it will sometimes make more sense to rename them to fit the actual problem. Finally, the ConcreteSubject and ConcreteObservers will be new classes derived from WmvcModel and WmvcView. Figure 7-2 shows how everything fits together.

Figure 7-2.
Wmvc implementation using Observer pattern

Command Pattern in Wmvc

One of the goals of the Wmvc Framework is to provide an easy to use interface to menu bar and tool bar commands. Even though the details of implementing a menu item, a tool bar button, or other Java Swing components are different, Wmvc provides a uniform interface to each component. This uniform interface is provided using the Command design pattern. Figure 7-3 shows the structure of the Command pattern as given in Design Patterns.

Figure 7-3.
Command Design Pattern Structure

As we noted earlier, the Command pattern provides a way to encapsulate a command request as an object without the object that issues the command needing to know what the response will be. In the case of Wmvc, it is the Swing library that issues a command after user input, and it is a Wmvc application that encapsulates the command response.

Within Wmvc, the class WmvcExecutor implements the Command class of the pattern. Wmvc uses the name Executor rather than Command because it makes more sense within the framework. Design patterns are outlines of solutions to problems that can be adapted and applied to specific problems. In this case, we adapted the name.

Within the WmvcExecutor class is the execute() method which is invoked by the Swing system in response to user input. This is the behavior encapsulated by the Command pattern. Each command object (Swing component) invokes the execute() method, and is protected from knowing what happens then.

Other Patterns used in Wmvc and MovieCat

The MovieEditor is implemented as a Singleton pattern. The singleton pattern makes sure there will be only one MovieEditor object created. We want only one editor active at a time.

The MovieModel class uses the Iterator pattern to provide access to all the movies. This access is used by MovieListView to get the movies for the list. The Iterator is also used within MovieModel itself to find the correct place to add a new movie object.

Chapter Summary

Resources

Java Design Patterns: A Tutorial, James W. Cooper; Addison-Wesley, 2000, ISBN 0-201-48539-7.

Pattern Hatching: Design Patterns Applied, John Vlissides, Addison-Wesley, 1998, ISBN 0-201-43293-5.

Patterns in Java, A Catalog of Reusable Design Patterns Illustrated with UML, Volume 1, Mark Grand, Wiley, 1998, ISBN 0471258393.

Patterns Home Page - hillside.net/patterns/patterns.html.


TOC PREV NEXT INDEX

The Essence of Object-Oriented Programming with Java and UML (DRAFT)

Copyright © 2001 by Addison-Wesley

All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. You may view this document on a web browser, but you must not mirror or make local copies.