148 Chapter 11 ■ Object-oriented design
11.1 Complete the design of the game presented in the chapter. In particular, establish
use cases and hence identify the methods associated with each class.
11.2 Design the software structure for each of the systems described in Appendix A.
11.3 Can OOD be characterized as a top-down, a bottom-up or some other process?
11.4 If programming and design are really two aspects of the same process (as OOD
suggests), does this mean that all designers must also be programmers?
11.5 To what extent is an OOD influenced by the class library of reusable components
that is available? To what extent must designers be knowledgeable about available
components?
11.6 What features or indicators might you use to help identify potential flaws in an OOD?
For example, what might be the problem with a class that has an excessive number of
methods? What could be done about this class? Again, is there a problem with a class
that only calls other classes and provides no methods that are used by other classes?
What might be done about this situation?
11.7 Design a program that allows two-dimensional shapes to be drawn on the screen. A
square, circle, triangle or rectangle can be selected from a list of options and posi-
tioned at a place on the screen using a mouse. A shape can be repositioned, delet-
ed or its size changed using the usual mouse operations.
11.8 Suggest features for a software tool that would support the creation, storage and
editing of class diagrams.
11.9 Suggest features for a software tool that would support the creation, storage and
editing of CRC cards. Suggest features for checking the consistency of a collection
of such cards.
11.10 Evaluate OOD under the following headings:
■ special features and strengths.
■ weaknesses
■ philosophy/perspective?
■ systematic?
■ appropriate applications
■ inappropriate applications
■ is the method top-down, bottom-up or something else?
■ good for large-scale design?
■ good for small-scale design?
■ can tools assist in using the method?
Exercises
•
BELL_C11.QXD 1/30/05 4:22 PM Page 148
Further reading 149
11.11 Compare and contrast the principles behind the following design methods:
■ functional decomposition
■ data structure design
■ data flow design
■ object oriented design.
Answers to self-test questions
11.1 There are objects laser and alien and therefore classes Laser and
Alien. Class Laser has a method checkAlienHit.
11.2
class Bomb
Instance variables
x
y
height
width
yStep
Methods
Bomb
move
display
getX
getY
getHeight
getWidth
Object-oriented design
An excellent book which presents a view of the process and notation of OOD and also
contains five extensive design case studies. Widely regarded as the definitive book on
OOD: G. Booch, Object-Oriented Design with Applications, Addison-Wesley, 2nd edn,
1993.
A wide-ranging survey of approaches and notations. Very readable. An excellent
overview of the different methods and notations: Edward Yourdon, Object-Oriented
Systems Design: An Integrated Approach, Prentice Hall, 1994.
Further reading
•
BELL_C11.QXD 1/30/05 4:22 PM Page 149
150 Chapter 11 ■ Object-oriented design
This book provides many valuable insights into the design and implementation of
object-oriented software. The early chapters provide an excellent and most readable
explanation of the principles of OOP. Examples are given using the programming
language Eiffel: B. Meyer, Object-Oriented Software Construction, Prentice Hall,
2nd edn, 1997.
This excellent book provides a coherent language independent methodology for OOD
known as “responsibility-driven design”: R.J. Wirfs-Brock, B. Wilkerson and L.
Weiner, Designing Object-Oriented Software, Prentice Hall, 1990.
Unified modeling language
Two simple books that one can read and understand: Martin Fowler with Kendall
Scott, UML Distilled, Addison-Wesley, 2000; Perdita Stevens with Rob Pooley,
Using UML, Addison-Wesley, 2000.
Object-oriented development
Written by a consultant who has seen many successful and unsuccessful projects. He
gives the results of his very practical experience. The book begins by identifying the
problems of software engineering. As part of this he suggests that successful pieces
of software have been written by just two people, young and without using
respectable methods. He goes on to look at the expected benefits of OOD. The
main part of the book is about practical OOD methods including management,
“software component foundries” and how to bring about change: Tom Love,
Object Lessons: Lessons Learned in OO Development Projects, SIGS Books, 1993.
This book complements Booch’s book about the technical aspects of design. It is a
companion book about the down-to-earth practical aspects of development. Very
readable: Grady Booch, Object Solutions: Managing the OO Project, Addison-Wesley,
1996.
BELL_C11.QXD 1/30/05 4:22 PM Page 150
Experienced programmers draw on half-remembered memories of software structures
that they have used themselves or seen used in the past. An example of a simple pro-
gramming pattern is the design of a program to find the largest number in an array of
numbers. The simplest algorithm uses a variable to record the largest value that has yet
been encountered. The program starts at the beginning of the array and proceeds item
by item, examining each number, updating this variable as necessary:
largest = list[0]
index = 0
while index <= list.size() do
if list[index] > largest then
largest = list[index]
end if
index = index + 1
end while
This is clearly a small piece of program that is easily constructed by any experienced
programmer, but to novice programmers, seeing this is something of a revelation. And
once seen, the programmer never forgets it. Or at least the programmer remembers
the idea of what is needed, rather than the detail. This is a software pattern. Over a
12.1
●
Introduction
CHAPTER
12
Design patterns
This chapter explains:
■ how to use design patterns during development
■ several major design patterns
■ some valuable anti-patterns.
>
>
BELL_C12.QXD 1/30/05 4:22 PM Page 151
152 Chapter 12 ■ Design patterns
period of time, experienced programmers build up a large repertoire of memories of
programming patterns such as this one.
A number of patterns have been identified, given names, cataloged and document-
ed in catalogs or books. These patterns are available for off-the-shelf use, just as classes
are available in class libraries. Software engineering patterns are patterns on a larger
scale than the simple program seen above. The established patterns specify the structure
of useful software at the architectural level. In object-oriented development, this means
structures expressed in terms of classes and their interrelationships.
The strength of design patterns is that good design ideas are recorded, given a name,
and explained with the aid of examples. This extends the vocabulary of software devel-
opers. It also extends the repertoire of ideas that they can use without reinventing the
wheel.
To make use of patterns, the software engineer needs some recollection of the stan-
dard patterns. This is obtained by browsing a patterns catalog prior to a project. The
engineer thereby retains some memory (perhaps only a partial recollection) of the pat-
terns, then, during the early phase of software architectural design, the engineer real-
izes that one or more patterns may be useful. They then consult the catalog to confirm
the appropriateness of the pattern and see exactly how to use it. The next step is to use
the pattern as part of the design.
In summary the stages are:
1. browse a design pattern catalog, to obtain some feel for the available patterns
2. embark on a new design with an awareness of the patterns
3. recognize the need for one of the established patterns
4. consult the catalog to check the applicability of the pattern
5. use the catalog for information on the how to use the pattern
6. use the pattern as part of the design.
As well as architectural structure, patterns are available for such domains as user
interfaces, file systems and multithreading. Patterns are also provided for activities such
as testing and project management.
In order to use design patterns the programmer needs considerable experience and
understanding of OOD and OOP.
Just as there are patterns (which are valuable structures) so there are anti-patterns,
which are undesirable structures. The reason for identifying and cataloguing anti-patterns
is to avoid them. We look at one such pattern.
In this chapter we present a number of useful patterns and use the cyberspace
invaders game as an example in explaining some of the patterns.
It bears repeating that one of the major goals of the object-oriented paradigm is to
produce reusable software components – components which can be reused both
within the application in which they were generated but also in future applications.
12.2
●
Inheritance
BELL_C12.QXD 1/30/05 4:22 PM Page 152
12.3 Delegation 153
The concepts of inheritance and subclassing supported by object-oriented languages
allow:
■ new classes of objects to be described as extensions or specializations of existing
classes, i.e. a new class can be defined as a subclass of an existing class
■ subclasses to inherit the behavior and state of their superclasses.
These concepts add extra dimensions to the design process. Taking into account
inheritance means that a major design goal is to factor the responsibilities within a
hierarchy of classes so that a responsibility attached to a superclass can be shared by
all subclasses.
In Chapter 13 on refactoring we will see how the design of the cyberspace invaders
program can be improved using inheritance.
This is probably the simplest and most obvious pattern. It describes the situation where
one class uses another. Delegation is worth emphasizing as a pattern because there is
sometimes a tendency to use inheritance too enthusiastically. Delegation is, in fact, a
more general way of extending the functionality of a class.
As an example, we will use another game, draughts (UK) or checkers (US). This
game takes place on a chess board with a set of black pieces and a set of white pieces.
Let us image a program that displays the board and the pieces on the screen as a game
is played. A natural (but as we shall see later flawed) structure would be to see that black
and white pieces are instances of class
Black and White and that these are in turn sub-
classes of class
Piece. The class diagram, showing inheritance, is shown in Figure 12.1.
However, there is a problem. When a piece reaches the end of the board, it becomes
crowned and thereby gains extra powers. How do we accommodate this in the rela-
tionships between classes? The trouble is that once an object is an instance of
White, it
remains a
White. Objects cannot change their class. So inheritance, though appealing,
is inappropriate. A better relationship is shown in Figure 12.2. Here classes
Black,
White, CrownedWhite and CrownedBlack use class Piece in the delegation pattern.
Inheritance is absent from this pattern. The class
Piece still incorporates all the shared
features of the original class
Piece – features such as the position on the board.
12.3
●
Delegation
Piece
Black White
Figure 12.1 Game of draughts showing inheritance
BELL_C12.QXD 1/30/05 4:22 PM Page 153
In some systems there only needs to be one instance of a class. Normally, of course,
someone writes a class so that any number of objects can be created from it. But occa-
sionally there should only be one. An example is an object to manage the communi-
cation between a system and the database. It would be confusing if any number of
classes were interacting with the database. Now it would be possible to try to achieve
this affect by telling all the programmers on the team that there is one copy of the
object, with such-and-such a name, written by Mo. But in a large and complex system,
this could be forgotten. We can instead legislate (with the help of compiler checking)
using the Singleton pattern.
Another example of the Singleton pattern is evident in the cyberspace invaders game
(Appendix A), where there should only be one object representing the defender.
12.4
●
Singleton
154 Chapter 12 ■ Design patterns
But the converse is not true.
The moral is:
■ anything that can be accomplished by inheritance can be achieved through delegation
■ everything that can be accomplished by delegation cannot be achieved through
inheritance. Delegation is more general mechanism than inheritance.
■ inheritance can be useful for modeling static “is-a” situations
■ inheritance is not appropriate for modeling “is-a-role-played-by” situations
■ delegation is more widely used than inheritance.
SELF-TEST QUESTION
12.1 A soldier in the army is a private, a sergeant or a general. Do we model
this as inheritance or delegation?
Piece
UsesUses
Black White
CrownedBlack CrownedWhite
Figure 12.2 Game of draughts using delegation
BELL_C12.QXD 1/30/05 4:22 PM Page 154
12.5 Factory method 155
The following coding shows how a singleton class Demo can be written in Java.
public class Demo {
private static final Demo demo = new Demo();
private Demo() {
}
private static Demo getInstance() {
return demo;
}
}
SELF-TEST QUESTION
12.2 Why is the constructor Demo labeled as private?
>
>
Suppose that we are writing some software to handle images. An image resides in a file
and there are several different common file formats – for example, jpeg and gif. We would
like the facility to create an object corresponding to a graphics image, in this manner:
Image image = new Image("picture.jpeg");
Once we have created the object, we can perform such operations as:
image.rotate(90);
image.display();
image.enlarge(2, 2);
The problem is that all of these methods will be different for each different graphics
file format. Indeed, the graphics object will be different for each file format. So one sin-
gle class –
Image – will not suffice; we need a different class for each file format. One
approach would be to provide a number of classes and expect a user to call the con-
structor for the relevant class like this:
JpegImage image = new JpegImage("fileName.jpeg");
But this is clumsy. The alternative is to create an abstract class Image that has a fac-
tory method
createImage. Now we create an image object conveniently like this:
Image image = Image.createImage("fileName.jpeg");
12.5
●
Factory method
BELL_C12.QXD 1/30/05 4:22 PM Page 155
156 Chapter 12 ■ Design patterns
createImage is class (static) method of the class Image. It looks at the extension of
the file name parameter and creates an appropriate object. For example, if the file type
is jpeg, it creates a subclass of
Image suitable for jpeg images. The sole purpose of this
method is to create the appropriate object, making the choice at run time. So now users
can treat all image file types in the same manner. The code for the factory method is:
class Image {
public static Image createImage(String fileName) {
String extension = getExtension(fileName);
if (extension.equals("jpeg"))
return (new JpegImage(fileName));
if (extension.equals("gif"))
return (new GifImage(fileName));
}
}
Here we have used a method getExtension (not shown) that returns the exten-
sion part of a file name.
We have buried the code that creates an appropriate class within the factory method,
providing a simple interface to the users.
Why could we not simply use the constructor method of class
Image? The answer is
that a constructor can only return an object of its own class. This is a limitation of con-
structors and, if we need to do anything different, we need to use a factory method.
Suppose you write a group of classes that perform some useful functions. It could be a
filing system that allows other classes (users) to open a file, close a file, read and write
information. One option is to tell users which classes to use and how (Figure 12.3, left-
hand diagram). However, this means that a user needs to understand the structure of
the subsystem to use it effectively. In addition, changes to the structure of the subsys-
tem may require changes to its users.
A better option (Figure 12.3, right-hand diagram) is to tell users to use one class –
a façade class. The façade class presents a clean and simple interface for users. It has
12.6
●
Façade
>
>
User
User
Façade
Figure 12.3 The Façade pattern
BELL_C12.QXD 1/30/05 4:22 PM Page 156
12.8 Model, view controller (observer, observable) 157
methods that provide all the functionality of the system. The detailed structure of the
system is hidden from its users. The façade class knows about the structure of the group
of classes and uses them as necessary. However, the classes in the group do not need to
know about the façade class, so any changes to the group do not impact on the users.
An immutable object is one that, once created, does not change its state. In the cyber-
space invaders game, there could be objects that do not move and do not change while
the game is in progress. These objects do not change their state (their internal vari-
ables). We can write an Immutable class by providing methods to access the values of
the object, but none to change them. The variables within an immutable class must not
be declared as constants, because they are changed (once) by the constructor method.
Many software systems have at their center a model or a simulation of the application of
interest. The simulation consists of objects and a set of rules governing how they interact.
In the cyberspace invaders game, the model consists of such objects as the alien, lasers and
bombs that move and interact according to certain rules. The model ensures that bombs
moves vertically. If a bomb strikes the defender, the user loses and the game is over.
The core model is surrounded by classes that support a user interface. The user inter-
face consists of two parts: the elements that control the system (inputs) and the ele-
ments that allow us to view information (the outputs). In the game, the user moves the
mouse to move the defender object and can fire a laser by clicking on the mouse but-
ton. These are controls. The screen shows the position of the objects, such as the alien
and a laser. These are outputs (the view).
To summarize, systems often have three components:
■ the model
■ the view
■ the controller.
The MVC pattern recognizes that many systems have this three-part structure –
model, view and controller – and that the software architecture should be explicitly par-
titioned in the same way. This has the advantage that the view and/or the control can be
changed without changing the core. For example, the user could control the defender
object with a joystick instead of the mouse, or the display could be sent across the inter-
net to the screens of multiple players. So, if the system is partitioned, we can easily change
the view or the control or both.
For this pattern to work properly there has to be clear communication between the
three components:
■ when the user alters a control, the model must be told
■ when the model changes, the view must be told.
12.8
●
Model, view controller (observer, observable)
12.7
●
Immutable
BELL_C12.QXD 1/30/05 4:22 PM Page 157