0% found this document useful (0 votes)
698 views

Object Oriented Design and Patterns

This chapter introduces Java programming concepts including "Hello World" examples, documentation comments, primitive types, control flow statements, object references, parameter passing, packages, exception handling, strings, and common Java classes like ArrayList and LinkedLists. It discusses how to set up a development environment and compile/run Java programs from the command line or using BlueJ.

Uploaded by

altafvasi9380
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
698 views

Object Oriented Design and Patterns

This chapter introduces Java programming concepts including "Hello World" examples, documentation comments, primitive types, control flow statements, object references, parameter passing, packages, exception handling, strings, and common Java classes like ArrayList and LinkedLists. It discusses how to set up a development environment and compile/run Java programs from the command line or using BlueJ.

Uploaded by

altafvasi9380
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 204

Object-Oriented Design & Patterns

Cay S. Horstmann

Chapter 1

A Crash Course in Java

Chapter Topics
 Hello, World in Java
 Documentation Comments
 Primitive Types
 Control Flow Statements
 Object References
 Parameter Passing
 Packages
 Basic Exception Handling
 Strings
 Reading Input
 Array Lists and Linked Lists
 Arrays
 Static Fields and Methods
 Programming Style

1
"Hello, World" in Java
 Simple but typical class

Ch1/helloworld/Greeter.java

 Features:
o Constructor Greeter(String aName)
o Method sayHello()
o Instance field name
 Each feature is tagged public or private

"Hello, World" in Java


 Construct new objects with new operator

new Greeter("World")

 Can invoke method on newly constructed object

new Greeter("World").sayHello()

 More common: store object reference in object variable

Greeter worldGreeter = new Greeter("World");

 Then invoke method on variable:

String greeting = worldGreeter.sayHello();

"Hello, World" in Java


 Construct separate class to test your class

Ch1/helloworld/GreeterTest.java

 main method is called when program starts


 main is static: it doesn't operate on any objects
 There are no objects yet when main starts
 In OO program, main constructs objects and invokes methods

Using the SDK


 Create a new directory to hold your files
 Use a text editor to prepare files (Greeter.java, GreeterTest.java)

2
 Open a shell window
 cd to directory that holds your files
 Compile and run

javac GreeterTest.java
java GreeterTest

Note that Greeter.java is automatically compiled.

 Output is shown in shell window

Using the SDK

Using BlueJ
 Download BlueJ from http://www.bluej.org
 No test program required
 Select Project->New and supply directory name
 Click on New Class... and type in Greeter class
 Compile the class
 Right-click the class to construct an object
 Right-click the object to invoke a method

Using BlueJ

3
Documentation Comments
 Delimited by /** ... */
 First sentence = summary
 @param parameter explanation
 @return explanation
 Javadoc utility extracts HTML file

Documentation Comments - Summary

4
Documentation Comments - Detail

5
Documentation Comments
 Easy to keep documentation in sync with code
 You must document all classes and methods
 The pros do it--check out the API docs
 Install and bookmark the API docs now!

Documentation Comments - API Docs

6
Primitive Types
 8 primitive types
 int, long, short, byte
 double, float
 char
 boolean
 suffixes L = long, F = float
 character constants 'a', '\n', '\x2122'
 Casts (int) x, (float) x
 Math class has methods that operate on numbers:

y = Math.sqrt(x);

Control Flow
 if
 while
 do/while
 for
 Variable can be declared in for loop:

for (int i = 1; i <= n; i++)


{
. . .
}
// i no longer defined here

7
Object References
 Object variable holds a reference
 Greeter worldGreeter = new Greeter("World");

 Can have multiple references to the same object

Greeter anotherGreeter = worldGreeter;

 After applying mutator method, all references access modified object

anotherGreeter.setName("Dave");
// now worldGreeter.sayHello() returns "Hello, Dave!"

The null Reference


 null refers to no object
 Can assign null to object variable:

worldGreeter = null;

 Can test whether reference is null

if (worldGreeter == null) . . .

 Dereferencing null causes NullPointerException

The this Reference

8
 Refers to implicit parameter of method call
 Example: Equality testing

public boolean equals(Greeter other)


{
if (this == other) return true;
return name.equals(other.name);
}

 Example: Constructor

public Greeter(String name)


{
this.name = name;
}

Parameter Passing
 Java uses "call by value":
Method receives copy of parameter value
 Copy of object reference lets method modify object

public void copyNameTo(Greeter other)


{
other.name = this.name;
}
 Greeter worldGreeter = new Greeter("World");
Greeter daveGreeter = new Greeter("Dave");
worldGreeter.copyNameTo(daveGreeter);

No Reference Parameters
 Java has no "call by reference"
 public void copyLengthTo(int n)
{
n = name.length();
}
public void copyGreeterTo(Greeter other)
{
other = new Greeter(name);
}

9
 Neither call has any effect after the method returns

int length = 0;
worldGreeter.copyLengthTo(length); // length still 0
worldGreeter.copyGreeterTo(daveGreeter) // daveGreeter unchanged

Packages
 Classes are grouped into packages
 Package names are dot-separated identifier sequences

java.util
javax.swing
com.sun.misc
edu.sjsu.cs.cs151.alice

 Unique package names: start with reverse domain name

Packages
 Add package statement to top of file

package edu.sjsu.cs.cs151.alice;
public class Greeter { . . . }

 Class without package name is in "default package"


 Full name of class = package name + class name

java.util.ArrayList
javax.swing.JOptionPane

Importing Packages
 Tedious to use full class names
 import allows you to use short class name

import java.util.ArrayList;
. . .
ArrayList a; // i.e. java.util.ArrayList

 Can import all classes from a package

import java.util.*;

Importing Packages
 Cannot import from multiple packages

10
import java.*.*; // NO

 If a class occurs in two imported packages, import is no help.

import java.util.*;
import java.sql.*;
. . .
java.util.Date d; // Date also occurs in java.sql

 Never need to import java.lang.

Packages and Directories


 Package name must match subdirectory name.

edu.sjsu.cs.sjsu.cs151.alice.Greeter

must be in subdirectory

basedirectory/edu/sjsu/cs/sjsu/cs151/alice

 Always compile from the base directory

javac edu/sjsu/cs/sjsu/cs151/alice/Greeter.java

or

javac edu\sjsu\cs\sjsu\cs151\alice\Greeter.java

 Always run from the base directory

java edu.sjsu.cs.cs151.alice.GreeterTest

Exception Handling
 Example: NullPointerException

11
String name = null;
int n = name.length(); // ERROR

 Cannot apply a method to null


 Virtual machine throws exception
 Unless there is a handler, program exits with stack trace

Exception in thread "main" java.lang.NullPointerException


at Greeter.sayHello(Greeter.java:25)
at GreeterTest.main(GreeterTest.java:6)

Checked and Unchecked Exceptions


 Compiler tracks only checked exceptions
 NullPointerException is not checked
 IOException is checked
 Generally, checked exceptions are thrown for reasons beyond the programmer's
control
 Two approaches for dealing with checked exceptions
o Declare the exception in the method header (preferred)
o Catch the exception

Declaring Checked Exceptions


 Example: Opening a file may throw FileNotFoundException:

public void read(String filename) throws FileNotFoundException


{
FileReader reader = new FileReader(filename);
. . .
}

 Can declare multiple exceptions

public void read(String filename)


throws IOException, ClassNotFoundException

public static void main(String[] args)


throws IOException, ClassNotFoundException

Catching Exceptions
 try
{
code that might throw an IOException
}
catch (IOException exception)
{

12
take corrective action
}
 Corrective action can be:
o Notify user of error and offer to read another file
o Log error in error report file
o In student programs: print stack trace and exit

exception.printStackTrace();
System.exit(1);

The finally Clause


 Cleanup needs to occur during normal and exceptional processing
 Example: Close a file
 FileReader reader = null;
try
{
reader = new FileReader(name);
...
}
finally
{
if (reader != null) reader.close();
}

Strings
 Sequence of Unicode characters
 length method yields number of characters
 "" is the empty string of length 0, different from null
 charAt method yields characters:
char c = s.charAt(i);

Strings
 substring method yields substrings:
"Hello".substring(1, 3) is "el"

 Use equals to compare strings


if (greeting.equals("Hello"))
 == only tests whether the object references are identical:
if ("Hello".substring(1, 3) == "el") ... // NO!

StringTokenizer

13
 Use StringTokenizer to break string into substrings

String countries = "Germany,France,Italy";


StringTokenizer tokenizer = new StringTokenizer(countries, ",");
while (tokenizer.hasMoreTokens())
{
String country = tokenizer.nextToken();
...
}

String concatenation
 + operator concatenates strings:

"Hello, " + name

 If one argument of + is a string, the other is converted into a string:

int n = 7;
String greeting = "Hello, " + n;
// yields "Hello, 7"

 toString method is applied to objects

Date now = new Date();


String greeting = "Hello, " + now;
// concatenates now.toString()
// yields "Hello, Wed Jan 17 16:57:18 PST 2001"

Converting Strings to Numbers


 Use static methods
Integer.parseInt
Double.parseDouble
 Example:

String input = "7";


int n = Integer.parseInt(input);
// yields integer 7

 If string doesn't contain a number, throws a


NumberFormatException(unchecked)

Reading Input
 Use input dialog:

String input = JOptionPane.showInputDialog("How old are you?");

14
 If user cancels, result is null:

if (input != null) age = Integer.parseInt(input);

Reading Input
 Must call System.exit(0)
 Ch1/input1/InputTest.java
 Also have message dialog

JOptionPane.showMessageDialog(null, "Hello, World");

Reading Input
 Read console input from System.in
 System.in is an InputStream: reads bytes
 We want a Reader that reads characters
 Turn System.in into InputStreamReader
 Also want to read entire lines
 Use BufferedReader:

BufferedReader console = new BufferedReader(


new InputStreamReader(System.in));
System.out.println("How old are you?");
String input = console.readLine();
int age = Integer.parseInt(input);

 Ch1/input2/InputTest.java

The ArrayList class

15
 Collects objects of any class type
 add appends to the end

ArrayList countries = new ArrayList();


countries.add("Belgium");
countries.add("Italy");
countries.add("Thailand");

 size method yields number of elements


for (int i = 0; i < countries.size(); i++) . . .
 get gets an element; must cast to correct type:
String country = (String)countries.get(i);
 set sets an element
countries.set(1, "France");

The ArrayList class


 Insert and remove elements in the middle
countries.add(1, "Germany");
countries.remove(0);
 Not efficient--use linked lists if needed frequently

Linked Lists
 Efficient insertion and removal

 add appends to the end

16
LinkedList countries = new LinkedList();
countries.add("Belgium");
countries.add("Italy");
countries.add("Thailand");

 Use iterators to edit in the middle

List Iterators
 Iterator points between list elements

 next retrieves element and advances iterator


ListIterator iterator = countries.listIterator();
while (iterator.hasNext())
{
String country = (String) iterator.next();
. . .
}
 add adds element before iterator position
 remove removes element returned by last call to next

Arrays
 Drawback of array lists: can't store numbers
 Arrays can store objects of any type, but their length is fixed
int[] numbers = new int[10];

17
 Array variable is a reference

Arrays
 length member yields number of elements

for (int i = 0; i < numbers.length; i++)

 Can have array of length 0; not the same as null:

numbers = new int[0];

 Array access with [] operator:


int n = numbers[i];
 Multidimensional array

int[][] table = new int[10][20];


int t = table[i][j];

Command-Line Arguments
 void main(String[] args)
 args parameter of main is initialized with command-line arguments
 Example:
java GreeterTest Mars

18
 args.length is 1
args[0] is "Mars"

Static Fields
 Shared among all instances of a class
 Example: shared random number generator

public class Greeter


{
. . .
private static Random generator;
}

 Example: shared constants

public class Math


{
. . .
public static final double PI = 3.14159265358979323846;
}

Static Methods
 Don't operate on objects
 Example: Math.sqrt
 Example: factory method

public static Greeter getRandomInstance()


{
if (generator.nextBoolean()) // note: generator is static
field
return new Greeter("Mars");
else
return new Greeter("Venus");
}

 Invoke through class:

Greeter g = Greeter.getRandomInstance();

 Static fields and methods should be rare in OO programs

Programming Style: Case Convention


 variables, fields and methods:
start with lowercase, use caps for new words:

19
name
sayHello

 Classes:
start with uppercase, use caps for new words:

Greeter
ArrayList

 Constants:
use all caps, underscores to separate words

PI
MAX_VALUE

Programming Style: Property Access


 Common to use get/set prefixes:

String getName()
void setName(String newValue)

 Boolean property has is/set prefixes:

public boolean isPolite()


public void setPolite(boolean newValue)

Programming Style: Braces


 "Allman" brace style: braces line up

public String sayHello()


{
return "Hello, " + name + "!";
}

 "Kernighan and Ritchie" brace style: saves a line

public String sayHello() {


return "Hello, " + name + "!";
}

Programming Style: Fields


 Some programmers put fields before methods:

public class Greeter


{

20
private String name;
public Greeter(String aName) { . . . }
. . .
}

 From OO perspective, it is better to list the public interface first


 All fields should be private
 Don't use default (package) visibility

Programming Style: Miscellaneous


 Spaces around operators, after keywords, but not after method names

Good: if (x > Math.sqrt(y))


Bad: if(x>Math.sqrt (y))

 Don't use C-style arrays:

Good: int[] numbers


Bad: int numbers[]

 No magic numbers

Good: h = HASH_MULTIPLIER * h + val[off];


Bad: h = 31 * h + val[off];

21
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 2

The Object-Oriented Design Process

Chapter Topics
 From Problem to Code
 The Object and Class Concepts
 Identifying Classes
 Identifying Responsibilities
 Relationships Between Classes
 Use Cases
 CRC Cards
 UML Class Diagrams
 Sequence Diagrams
 State Diagrams
 Using javadoc for Design Documentation
 Case Study: A Voice Mail System

From Problem to Code

22
Three Phases:

 Analysis
 Design
 Implementation

Case Study: Voice Mail System

Analysis Phase
Functional Specification

 Completely defines tasks to be solved


 Free from internal contradictions
 Readable both by domain experts and software developers
 Reviewable by diverse interested parties
 Testable against reality

Design Phase
Goals

 Identify classes
 Identify behavior of classes
 Identify relationships among classes

Artifacts

 Textual description of classes and key methods


 Diagrams of class relationships
 Diagrams of important usage scenarios
 State diagrams for objects with rich state

Implementation Phase
 Implement and test classes
 Combine classes into program
 Avoid "big bang" integration
 Prototypes can be very useful

Object and Class Concepts


 Object: Three characteristic concepts
o State

23
o Behavior
o Identity
 Class: Collection of similar objects

Identifying Classes
Rule of thumb: Look for nouns in problem description

 Mailbox
 Message
 User
 Passcode
 Extension
 Menu

Identifying Classes
Focus on concepts, not implementation

 MessageQueue stores messages


 Don't worry yet how the queue is implemented

Categories of Classes
 Tangible Things
 Agents
 Events and Transactions
 Users and Roles
 Systems
 System interfaces and devices
 Foundational Classes

Identifying Responsibilities
Rule of thumb: Look for verbs in problem description

Behavior of MessageQueue:

 Add message to tail


 Remove message from head
 Test whether queue is empty

Responsibilities

24
 OO Principle: Every operation is the responsibility of a single class
 Example: Add message to mailbox
 Who is responsible: Message or Mailbox?

Class Relationships
 Dependency ("uses")
 Aggregation ("has")
 Inheritance ("is")

Dependency Relationship
 C depends on D: Method of C manipulates objects of D
 Example: Mailbox depends on Message
 If C doesn't use D, then C can be developed without knowing about D

Coupling
 Minimize dependency: reduce coupling
 Example: Replace

void print() // prints to System.out

with

String getText() // can print anywhere

 Removes dependence on System, PrintStream

Aggregation
 Object of a class contains objects of another class
 Example: MessageQueue aggregates Messages
 Example: Mailbox aggregates MessageQueue
 Implemented through instance fields

Multiplicities
 1 : 1 or 1 : 0...1 relationship:

public class Mailbox


{
. . .
private Greeting myGreeting;
}

25
 1 : n relationship:

public class MessageQueue


{
. . .
private ArrayList elements;
}

Inheritance
 More general class = superclass
 More specialized class = subclass
 Subclass supports all method interfaces of superclass (but implementations may
differ)
 Subclass may have added methods, added state
 Subclass inherits from superclass
 Example: ForwardedMessage inherits from Message
 Example: Greeting does not inherit from Message (Can't store greetings in
mailbox)

Use Cases
 Analysis technique
 Each use case focuses on a specific scenario
 Use case = sequence of actions
 Action = interaction between actor and computer system
 Each action yields a result
 Each result has a value to one of the actors
 Use variations for exceptional situations

Sample Use Case


Leave a Message

1. Caller dials main number of voice mail system


2. System speaks prompt

Enter mailbox number followed by #

3. User types extension number


4. System speaks

You have reached mailbox xxxx. Please leave a message now

5. Caller speaks message


6. Caller hangs up

26
7. System places message in mailbox

Sample Use Case -- Variations


Variation #1

1.1. In step 3, user enters invalid extension number


1.2. Voice mail system speaks
You have typed an invalid mailbox number.
1.3. Continue with step 2.

Variation #2

2.1. After step 4, caller hangs up instead of speaking message


2.3. Voice mail system discards empty message

CRC Cards
 CRC = Classes, Responsibilities, Collaborators
 Developed by Beck and Cunningham
 Use an index card for each class
 Class name on top of card
 Responsibilities on left
 Collaborators on right

CRC Cards

CRC Cards

27
 Responsibilities should be high level
 1 - 3 responsibilities per card
 Collaborators are for the class, not for each responsibility

Walkthroughs
 Use case: "Leave a message"
 Caller connects to voice mail system
 Caller dials extension number
 "Someone" must locate mailbox
 Neither Mailbox nor Message can do this
 New class: MailSystem
 Responsibility: manage mailboxes

Walkthroughs

UML Diagrams
 UML = Unified Modeling Language
 Unifies notations developed by the "3 Amigos" Booch, Rumbaugh, Jacobson
 Many diagram types
 We'll use three types:
o Class Diagrams
o Sequence Diagrams
o State Diagrams

Class Diagrams

28
 Rectangle with class name
 Optional compartments
o Attributes
o Methods
 Include only key attributes and methods

Class Diagrams

Class Relationships

Multiplicities

29
 any number (0 or more): *
 one or more: 1..*
 zero or one: 0..1
 exactly one: 1

Composition
 Special form of aggregation
 Contained objects don't exist outside container
 Example: message queues permanently contained in mail box

Association
 Some designers don't like aggregation
 More general association relationship
 Association can have roles

Association
 Some associations are bidirectional
Can navigate from either class to the other
 Example: Course has set of students, student has set of courses
 Some associations are directed
Navigation is unidirectional
 Example: Message doesn't know about message queue containing it

30
Interface Types
 Interface type describes a set of methods
 No implementation, no state
 Class implements interface if it implements its methods
 In UML, use stereotype «interface»

Tips
 Use UML to inform, not to impress
 Don't draw a single monster diagram
 Each diagram must have a specific purpose
 Omit inessential details

Sequence Diagrams
 Each diagram shows dynamics of scenario
 Object diagram: class name underlined

Self call

31
Object Construction

State Diagram
 Use for classes whose objects have interesting states

32
Design Documentation
 Recommendation: Use Javadoc comments
 Leave methods blank

/**
Adds a message to the end of the new messages.
@param aMessage a message
*/
public void addMessage(Message aMessage)
{
}

 Don't compile file, just run Javadoc


 Makes a good starting point for code later

Case Study: Voice Mail System


 Use text for voice, phone keys, hangup
 1 2 ... 0 # on a single line means key
 H on a single line means "hang up"
 All other inputs mean voice
 In GUI program, will use buttons for keys (see ch. 4)

Use Case: Reach an Extension

33
1. User dials main number of system
2. System speaks prompt

Enter mailbox number followed by #

3. User types extension number


4. System speaks

You have reached mailbox xxxx. Please leave a message now

Use Case: Leave a Message


1. Caller carries out Reach an Extension
2. Caller speaks message
3. Caller hangs up
4. System places message in mailbox

Use Case: Log in


1. Mailbox owner carries out Reach an Extension
2. Mailbox owner types password and #
(Default password = mailbox number. To change, see Change the Passcode)
3. System plays mailbox menu:

Enter 1 to retrieve your messages.


Enter 2 to change your passcode.
Enter 3 to change your greeting.

Use Case: Retrieve Messages


1. Mailbox owner carries out Log in
2. Mailbox owner selects "retrieve messages" menu option
3. System plays message menu:

Press 1 to listen to the current message


Press 2 to delete the current message
Press 3 to save the current message
Press 4 to return to the mailbox menu

4. Mailbox owner selects "listen to current message"


5. System plays current new message, or, if no more new messages, current old
message.
Note: Message is played, not removed from queue
6. System plays message menu
7. User selects "delete current message". Message is removed.
8. Continue with step 3.

34
Use Case: Retrieve Messages
Variation #1

1.1. Start at Step 6


1.2. User selects "save current message".
Message is removed from new queue and appended to old queue
1.3. Continue with step 3.

Use Case: Change the Greeting


1. Mailbox owner carries out Log in
2. Mailbox owner selects "change greeting" menu option
3. Mailbox owner speaks new greeting
4. Mailbox owner presses #
5. System sets new greeting

Use Case: Change the Greeting


Variation #1: Hang up before confirmation

1.1. Start at step 3.


1.2. Mailbox owner hangs up.
1.3. System keeps old greeting.

Use Case: Change the Passcode


1. Mailbox owner carries out Log in
2. Mailbox owner selects "change passcode" menu option
3. Mailbox owner dials new passcode
4. Mailbox owner presses #
5. System sets new passcode

Use Case: Change the Passcode


Variation #1: Hang up before confirmation

1.1. Start at step 3.


1.2. Mailbox owner hangs up.
1.3. System keeps old passcode.

CRC Cards for Voice Mail System

35
Some obvious classes

 Mailbox
 Message
 MailSystem

Initial CRC Cards: Mailbox

Initial CRC Cards: MessageQueue

Initial CRC Cards: MailSystem

36
Telephone
 Who interacts with user?
 Telephone takes button presses, voice input
 Telephone speaks output to user

Telephone

Connection
 With whom does Telephone communicate
 With MailSystem?
 What if there are multiple telephones?
 Each connection can be in different state
(dialing, recording, retrieving messages,...)
 Should mail system keep track of all connection states?
 Better to give this responsibility to a new class

Connection

37
Analyze Use Case: Leave a message
1. User dials extension. Telephone sends number to Connection
(Add collaborator Telephone to Connection)
2. Connection asks MailSystem to find matching Mailbox
3. Connection asks Mailbox for greeting
(Add responsibility "manage greeting" to Mailbox,
add collaborator Mailbox to Connection)
4. Connection asks Telephone to play greeting
5. User speaks greeting. Telephone asks Connection to record it.
(Add responsibility "record voice input" to Connection)
6. User hangs up. Telephone notifies Connection.
7. Connection constructs Message
(Add card for Message class,
add collaborator Message to Connection)
8. Connection adds Message to Mailbox

Result of Use Case Analysis

38
Result of Use Case Analysis

Result of Use Case Analysis

Result of Use Case Analysis

39
Analyse Use Case: Retrieve messages
1. User types in passcode. Telephone notifies Connection
2. Connection asks Mailbox to check passcode.
(Add responsibility "manage passcode" to Mailbox)
3. Connection sets current mailbox and asks Telephone to speak menu
4. User selects "retrieve messages". Telephone passes key to Connection
5. Connection asks Telephone to speak menu
6. User selects "listen to current message". Telephone passes key to Connection
7. Connection gets first message from current mailbox.
(Add "retrieve messages" to responsibility of Mailbox).
Connection asks Telephone to speak message
8. Connection asks Telephone to speak menu
9. User selects "save current message". Telephone passes key to Connection
10. Connection tells Mailbox to save message
(Modify responsibility of Mailbox to "retrieve,save,delete messages")
11. Connection asks Telephone to speak menu

Result of Use Case Analysis

40
CRC Summary
 One card per class
 Responsibilities at high level
 Use scenario walkthroughs to fill in cards
 Usually, the first design isn't perfect.
(You just saw the author's third design of the mail system)

UML Class Diagram for Mail System


 CRC collaborators yield dependencies
 Mailbox depends on MessageQueue
 t depends on Mailbox
 Connection depends on Telephone, MailSystem, Message,
Mailbox
 Telephone depends on Connection

Dependency Relationships

41
Aggregation Relationships
 A mail system has mailboxes
 A mailbox has two message queues
 A message queue has some number of messages
 A connection has a current mailbox.
 A connection has references to a mailsystem and a telephone

UML Class Diagram for Voice Mail System

Sequence Diagram for Use Case: Leave a message

42
Interpreting a Sequence Diagram
 Each key press results in separate call to dial, but only one is shown
 Connection wants to get greeting to play
 Each mailbox knows its greeting
 Connection must find mailbox object:
Call findMailbox on MailSystem object
 Parameters are not displayed (e.g. mailbox number)
 Return values are not displayed (e.g. found mailbox)
 Note that connection holds on to that mailbox over multiple calls

Sequence Diagram for Use Case: Retrieve messages

43
Connection State Diagram

Java Implementation

44
 Ch2/mail/Message.java
 Ch2/mail/MessageQueue.java
 Ch2/mail/Mailbox.java
 Ch2/mail/Connection.java
 Ch2/mail/MailSystem.java
 Ch2/mail/Telephone.java
 Ch2/mail/MailSystemTest.java

45
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 3

The Object-Oriented Design Process

Chapter Topics
 An overview of the Date classes in the Java library
 Designing a Day class
 Three implementations of the Day class
 The importance of encapsulation
 Analyzing the quality of an interface
 Programming by contract
 Unit testing

Date Classes in Standard Library


 Many programs manipulate dates such as
"Saturday, February 3, 2001"
 Date class:

Date now = new Date();


// constructs current date/time

46
System.out.println(now.toString());
// prints date such as
// Sat Feb 03 16:34:10 PST 2001

 Date class encapsulates point in time

Methods of the Date class


boolean after(Date Tests if this date is after the specified date
other)
boolean before(Date Tests if this date is before the specified date
other)
int compareTo(Date Tells which date came before the other
other)
long getTime() Returns milliseconds since the epoch
(1970-01-01 00:00:00 GMT)
void setTime(long n) Sets the date to the given number of milliseconds since
the epoch

Methods of the Date class


 Deprecated methods omitted
 Date class methods supply total ordering on Date objects
 Convert to scalar time measure
 Note that before/after not strictly necessary
(Presumably introduced for convenience)

Points in Time

The GregorianCalendar Class


 The Date class doesn't measure months, weekdays, etc.
 That's the job of a calendar
 A calendar assigns a name to a point in time

47
 Many calendars in use:
o Gregorian
o Contemporary: Hebrew, Arabic, Chinese
o Historical: French Revolutionary, Mayan

Date Handling in the Java Library

Designing a Day Class


 Custom class, for teaching/learning purpose
 Use the standard library classes, not this class, in your own programs
 Day encapsulates a day in a fixed location
 No time, no time zone
 Use Gregorian calendar

Designing a Day Class


 Answer questions such as
o How many days are there between now and the end of the year?
o What day is 100 days from now?

Designing a Day Class

48
Designing a Day Class
 daysFrom computes number of days between two days:

int n = today.daysFrom(birthday);

 addDays computes a day that is some days away from a given day:

Day later = today.addDays(999);

 Mathematical relationship:

d.addDays(n).daysFrom(d) == n
d1.addDays(d2.daysFrom(d1)) == d2

 Clearer when written with "overloaded operators":

(d + n) - d == n
d1 + (d2 - d1) == d2

 Constructor Date(int year, int month, int date)


 getYear, getMonth, getDate acccesors

Implementing a Day Class


 Straightforward implementation:

private int year


private int month
private int date

 addDays/daysBetween tedious to implement


o April, June, September, November have 30 days

49
o February has 28 days, except in leap years it has 29 days
o All other months have 31 days
o Leap years are divisible by 4, except after 1582, years divisible by 100 but
not 400 are not leap years
o There is no year 0; year 1 is preceded by year -1
o In the switchover to the Gregorian calendar, ten days were dropped:
October 15, 1582 is preceded by October 4

Implementing a Day Class


 Ch3/code/day1/Day.java
 Ch3/code/day1/DayTest.java
 Note private helper methods
 Computations are inefficient: a day at a time

Second Implementation
 For greater efficiency, use Julian day number
 Used in astronomy
 Number of days since Jan. 1, 4713 BCE
 May 23, 1968 = Julian Day 2,440,000
 Greatly simplifies date arithmetic
 Ch3/code/day2/Day.java

Third Implementation
 Now constructor, accessors are inefficient
 Best of both worlds: Cache known Julian, y/m/d values
 Ch3/code/day3/Day.java
 Which implementation is best?

The Importance of Encapsulation


 Even a simple class can benefit from different implementations
 Users are unaware of implementation
 Public instance variables would have blocked improvement
o Can't just use text editor to replace all

d.year

with

d.getYear()

o How about

50
d.year++?
o d = new Day(d.getDay(), d.getMonth(), d.getYear() + 1)
oUgh--that gets really inefficient in Julian representation
 Don't use public fields, even for "simple" classes

Accessors and Mutators


 Mutator: Changes object state
 Accessor: Reads object state without changing it
 Day class has no mutators!
 Class without mutators is immutable
 String is immutable
 Date and GregorianCalendar are mutable

Don't Supply a Mutator for every Accessor


 Day has getYear, getMonth, getDate accessors
 Day does not have setYear, setMonth,setDate mutators
 These mutators would not work well
o Example:

Day deadline = new Day(2001, 1, 31);


deadline.setMonth(2); // ERROR
deadline.setDate(28);

o Maybe we should call setDate first?

Day deadline = new Day(2001, 2, 28);


deadline.setDate(31); // ERROR
deadline.setMonth(3);

 GregorianCalendar implements confusing rollover.


o Silently gets the wrong result instead of error.
 Immutability is useful

Sharing Mutable References


 References to immutable objects can be freely shared
 Don't share mutable references
 Example

class Employee
{
. . .
public String getName() { return name; }
public double getSalary() { return salary; }
public Date getHireDate() { return hireDate; }

51
private String name;
private double salary;
private Date hireDate;
}

Sharing Mutable References


 Pitfall:

Employee harry = . . .;
Date d = harry.getHireDate();
d.setTime(t); // changes Harry's state!!!

 Remedy: Use clone

public Date getHireDate()


{
return (Date)hireDate.clone();
}

Sharing Mutable References

Final Instance Fields


 Good idea to mark immutable instance fields as final
private final int day;
 final object reference can still refer to mutating object
private final ArrayList elements;
 elements can't refer to another array list
 The contents of the array list can change

Separating Accessors and Mutators

52
 If we call a method to access an object, we don't expect the object to mutate
 Rule of thumb:
Mutators should return void
 Example of violation:

StringTokenizer t = . . .;
String s = t.nextToken();

 Yields current token and advances iteration


 What if I want to read the current token again?

Separating Accessors and Mutators


 Better interface:

String getToken();
void nextToken();

 Even more convenient:

String getToken();
String nextToken(); // returns current

 Refine rule of thumb:


Mutators can return a convenience value, provided there is also an accessor to get
the same value

Side Effects
 Accessor: no change to object
 Mutator: changes object state
 Side effect: change to another object
o Parameter variable
o static object
 Avoid side effects--they confuse users
 Good example, no side effect:

a.addAll(b)

mutates a but not b

Side Effects
 Date formatting (basic):

53
SimpleDateFormat formatter = . . .;
String dateString = "January 11, 2012";
Date d = formatter.parse(dateString);

 Advanced:

FieldPosition position = . . .;
Date d = formatter.parse(dateString, position);

 Side effect: updates position


 Design could be better: add position to formatter state

Side Effects
 Avoid modifying static objects
 Example: System.out
 Don't print error messages to System.out:

if (newMessages.isFull())
System.out.println("Sorry--no space");

 Your classes may need to run in an environment without System.out


 Rule of thumb: Minimize side effects

Law of Demeter
 Example: Mail system in chapter 2
Mailbox currentMailbox = mailSystem.findMailbox(...);
 Breaks encapsulation
 Suppose future version of MailSystem uses a database
 Then it no longer has mailbox objects
 Common in larger systems
 Karl Lieberherr: Law of Demeter
 Demeter = Greek goddess of agriculture, sister of Zeus

Law of Demeter
 The law: A method should only use objects that are
o instance fields of its class
o parameters
o objects that it constructs with new
 Shouldn't use an object that is returned from a method call
 Remedy in mail system: Delegate mailbox methods to mail system
mailSystem.getCurrentMessage(int mailboxNumber);
mailSystem.addMessage(int mailboxNumber, Message msg);
. . .
 Rule of thumb, not a mathematical law

54
Quality of Class Interface
 Customers: Programmers using the class
 Criteria:
o Cohesion
o Completeness
o Convenience
o Clarity
o Consistency
 Engineering activity: make tradeoffs

Cohesion
 Class describes a single abstraction
 Methods should be related to the single abstraction
 Bad example:

public class Mailbox


{
public addMessage(Message aMessage) { ... }
public Message getCurrentMessage() { ... }
public Message removeCurrentMessage() { ... }
public void processCommand(String command) { ... }
...
}

Completeness
 Support operations that are well-defined on abstraction
 Potentially bad example: Date

Date start = new Date();


// do some work
Date end = new Date();

 How many milliseconds have elapsed?


 No such operation in Date class
 Does it fall outside the responsibility?
 After all, we have before, after, getTime

Convenience
 A good interface makes all tasks possible . . . and common tasks simple
 Bad example: Reading from System.in
 Why doesn't System.in have a readLine method?
 After all, System.out has println.

55
 Why can't I make a BufferedReader from an input stream?
 After all, I can make a PrintWriter from an output stream.

Clarity
 Confused programmers write buggy code
 Bad example: Removing elements from LinkedList
 Reminder: Standard linked list class

LinkedList countries = new LinkedList();


countries.add("A");
countries.add("B");
countries.add("C");

 Iterate through list:

ListIterator iterator = countries.listIterator();


while (iterator.hasNext())
System.out.println(iterator.next());

Clarity
 Iterator between elements
 Like blinking caret in word processor
 add adds to the left of iterator (like word processor):
 Add X before B:

ListIterator iterator = countries.listIterator(); // |ABC


iterator.next(); // A|BC
iterator.add("France"); // AX|BC

 To remove first two elements, you can't just "backspace"


 remove does not remove element to the left of iterator
 From API documentation:
Removes from the list the last element that was returned by next or previous. This
call can only be made once per call to next or previous. It can be made only if add
has not been called after the last call to next or previous.
 Huh?

Consistency
 Related features of a class should have matching
o names
o parameters
o return values
o behavior

56
 Bad example:

new GregorianCalendar(year, month - 1, day)

 Why is month 0-based?

Consistency
 Bad example: String class

s.equals(t) / s.equalsIgnoreCase(t)

 But

boolean regionMatches(int toffset,


String other, int ooffset, int len)
boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len)

 Why not regionMatchesIgnoreCase?


 Very common problem in student code

Programming by Contract
 Spell out responsibilities
o of caller
o ofimplementor
 Increase reliability
 Increase efficiency

Preconditions
 Caller attempts to remove message from empty MessageQueue
 What should happen?
 MessageQueue can declare this as an error
 MessageQueue can tolerate call and return dummy value
 What is better?

Preconditions
 Excessive error checking is costly
 Returning dummy values can complicate testing
 Contract metaphor
o Service provider must specify preconditions
o If precondition is fulfilled, service provider must work correctly

57
o Otherwise, service provider can do anything
 When precondition fails, service provider may
o throw exception
o return false answer
o corrupt data

Preconditions
/**
Remove message at head
@return the message at the head
@precondition size() > 0
*/
Message removeFirst()
{
return (Message)elements.remove(0);
}

 What happens if precondition not fulfilled?


 IndexOutOfBoundsException
 Other implementation may have different behavior

Circular Array Implementation


 Efficient implementation of bounded queue
 Avoids inefficient shifting of elements
 Circular: head, tail indexes wrap around
 Ch3/queue/MessageQueue.java

Inefficient Shifting of Elements

A Circular Array

58
Wrapping around the End

Preconditions
 In circular array implementation, failure of remove precondition corrupts queue!
 Bounded queue needs precondition for add
 Naive approach:
@precondition size() < elements.length
 Precondition should be checkable by caller
 Better:
@precondition size() < getCapacity()

Assertions
 Mechanism for warning programmers
 Can be turned off after testing
 Useful for warning programmers about precondition failure
 Syntax:

assert condition;
assert condition : explanation;

 Throws AssertionError if condition false and checking enabled

Assertions

59
public Message removeFirst()
{
assert count > 0 : "violated precondition size() > 0";
Message r = elements[head];
. . .
}

 During testing, run with

java -enableassertions MyProg

Exceptions in the Contract


/**
. . .
@throws IllegalArgumentException if queue is empty
*/
public Message removeFirst()
{
if (count == 0)
throw new IllegalArgumentException();
Message r = elements[head];
. . .
}

 Exception throw part of the contract


 Caller can rely on behavior
 Exception throw not result of precondition violation
 This method has no precondition

Postconditions
 Conditions that the service provider guarantees
 Every method promises description, @return
 Sometimes, can assert additional useful condition
 Example: add method

@postcondition size() > 0

 Postcondition of one call can imply precondition of another:

q.add(m1);
m2 = q.remove();

Class Invariants
 Condition that is
o true after every constructor

60
o preserved by every method
(if it's true before the call, it's again true afterwards)
 Useful for checking validity of operations

Class Invariants
 Example: Circular array queue

0 <= head && head < elements.length

 First check it's true for constructor


o Sets head = 0
o Need precondition size > 0!
 Check mutators. Start with add
o Sets headnew = (headold + 1) % elements.length
o We know headold > 0 (Why?)
o % operator property:

0 <= headnew && headnew < elements.length

 What's the use? Array accesses are correct!

return elements[head];

Class Invariants
 Example: Queue with array list
elements only contains objects of type Message
 Ch2/mail/MessageQueue.java
 It's true for constructor.
elements is initially empty
 Check mutators. Start with add
Parameter type is Message
 What's the use? Casts are correct!
return (Message)elements.remove(0);

Unit Testing
 Unit test = test of a single class
 Design test cases during implementation
 Run tests after every implementation change
 When you find a bug, add a test case that catches it

JUnit

61
JUnit
 Test class name = tested class name + Test
 Test methods start with test

import junit.framework.*;
public class DayTest extends TestCase
{
public void testAdd() { ... }
public void testDaysBetween() { ... }
. . .
}

JUnit
 Each test case ends with assertion
 Test framework catches assertion failures

public void testAdd()


{
Day d1 = new Day(1970, 1, 1);
int n = 1000;
Day d2 = d1.addDays(n);
assert d2.daysFrom(d1) == n;
}

62
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 4

Interfaces and Polymorphism

Chapter Topics
 Displaying an Image
 Polymorphism
 Drawing Shapes
 The Comparable Interface
 The Comparator Interface
 Anonymous Classes
 Frames and User Interface Components
 User Interface Actions
 Timers
 Designing an Interface

Displaying an Image
 Use JOptionPane to display message:

63
JOptionPane.showMessageDialog(null, "Hello, World!");

 Note icon to the left

Displaying an Image
 Can specify arbitrary image file

JOptionPane.showMessageDialog(
null,
"Hello, World!",
"Message",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("globe.gif"));

Displaying an Image
 What if we don't want to generate an image file?
 Fortunately, can use any class that implements Icon interface type
 ImageIcon is one such class
 Easy to supply your own class

64
The Icon Interface Type
public interface Icon
{
int getIconWidth();
int getIconHeight();
void paintIcon(Component c, Graphics g, int x, int y)
}

Interface Types
 No implementation
 Implementing class must supply implementation of all methods
 Ch4/icon2/MarsIcon.java
 showMessageDialog expects Icon object
 Ok to pass MarsIcon
 Ch4/icon2/IconTest.java

The Icon Interface Type and Implementing Classes

Polymorphism
 public static void showMessageDialog(...Icon anIcon)

65
 showMessageDialog shows
o icon
o message
o OK button
 showMessageDialog must compute size of dialog
 width = icon width + message size + blank size
 How do we know the icon width?

int width = anIcon.getIconWidth();

Polymorphism
 showMessageDialog doesn't know which icon is passed
o ImageIcon?
o MarsIcon?
o . . .?
 The actual type of anIcon is not Icon
 There are no objects of type Icon
 anIcon belongs to a class that implements Icon
 That class defines a getIconWidth method

A Variable of Interface Type

Polymorphism
 Which getIconWidth method is called?
 Could be
o MarsIcon.getIconWidth
o ImageIcon.getIconWidth
o ...
 Depends on object to which anIcon reference points, e.g.

showMessageDialog(..., new MarsIcon(50))

 Polymorphism: Select different methods according to actual object type

66
Benefits of Polymorphism
 Loose coupling
o showMessageDialog decoupled from ImageIcon
o Doesn't need to know about image processing
 Extensibility
o Client can supply new icon types

Drawing Shapes
 paintIcon method receives graphics context of type Graphics
 Actually a Graphics2D object in modern Java versions

public void paintIcon(Component c, Graphics g, int x, int y)


{
Graphics2D g2 = (Graphics2D)g;
. . .
}

 Can draw any object that implements Shape interface

Shape s = . . .;
g2.draw(s);

Drawing Rectangles and Ellipses


 Rectangle2D.Double constructed with
o top left corner
o width
o height
 g2.draw(new Rectangle2D.Double(x, y, width, height));

 For Ellipse2D.Double, specify bounding box

Drawing Ellipses

67
Drawing Line Segments
 Point2D.Double is a point in the plane
 Line2D.Double joins to points

Point2D.Double start = new Point2D.Double(x1, y1);


Point2D.Double end = new Point2D.Double(x2, y2);
Shape segment = new Line2D.Double(start, end);
g2.draw(segment);

Relationship Between Shape Classes

Drawing Text

68
 g2.drawString(text, x, y);
 x, y are base point coordinates

Filling Shapes
 Fill interior of shape

g2.fill(shape);

 Set color for fills or strokes:


g2.setColor(Color.red);

 Program that draws car


Ch4/icon3/CarIcon.java

The Comparable Interface Type


 Collections has static sort method:

ArrayList a = . . .
Collections.sort(a);

 Objects in list must implement the Comparable interface type

public interface Comparable


{
int compareTo(Object other);
}

 object1.compareTo(object2) returns
o Negative number if object1 less than object2
o 0 if objects identical

69
o Positive number if object1 greater than object2

The Comparable Interface Type


 sort method compares and rearranges elements
if (object1.compareTo(object2) > 0) . . .
 String class implements Comparable interface type: lexicographic (dictionary)
order
 Country class: compare countries by area
Ch4/sort1/Country.java
Ch4/sort1/CountrySortTest.java

The Comparator interface type


 How can we sort countries by name?
 Can't implement Comparable twice!
 Comparator interface type gives added flexibility

public interface Comparator


{
int compare(Object object1, Object object2);
}

 Pass comparator object to sort:

Collections.sort(list, comp);

The Comparator interface type


 Ch4/sort2/CountryComparatorByName.java
Ch4/sort2/ComparatorTest.java
 Comparator object is a function object
 This particular comparator object has no state
 State can be useful, e.g. flag to sort in ascending or descending order

Anonymous Classes
 No need to name objects that are used only once

Collections.sort(countries,
new CountryComparatorByName());

 No need to name classes that are used only once

Comparator comp = new


Comparator()

70
{
public int compare(Object obj1, Object obj2)
{
Country country1 = (Country)obj1;
Country country2 = (Country)obj2;
return country1.getName().compareTo(country2.getName());
}
};

Anonymous Classes
 anonymous new expression:
o defines anonymous class that implements Comparator
o defines compare method of that class
o constructs one object of that class
 Cryptic syntax for very useful feature

Anonymous Classes
 Commonly used in factory methods:
public static Comparator comparatorByName()
{
return new Comparator()
{
public int compare(Object o1, Object o2) { . . .
}
};
}
 Collections.sort(a, Country.comparatorByName());
 Neat arrangement if multiple comparators make sense
(by name, by area, ...)

Frames
 Frame window has decorations
o title bar
o close box
o provided by windowing system
 JFrame frame = new JFrame();
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();

Adding Components
 Construct components

71
JButton helloButton = new JButton("Say Hello");

 Set content pane layout

Container contentPane = frame.getContentPane();


container.setLayout(new FlowLayout());

 Add components to content pane

contentPane.add(helloButton);

 Ch4/frame/FrameTest.java

User Interface Actions


 Previous program's buttons don't have any effect
 Add listener object(s) to button
 Belong to class implementing ActionListener interface type

public interface ActionListener


{
int actionPerformed(ActionEvent event);
}

 Listeners are notified when button is clicked

User Interface Actions


 Add action code into actionPerformed method
 Gloss over routine code

helloButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
textField.setText("Hello, World");
}
});

 When button is clicked, text field is set

Accessing Variables from Enclosing Scope

72
 Remarkable: Inner class can access variables from enclosing scope
e.g. textField
 Can access enclosing instance fields, local variables
 Local variables must be marked final
final JTextField textField = ...;

User Interface Actions


 Constructor attaches listener:

helloButton.addActionListener(listener);

 Button remembers all listeners


 When button clicked, button notifies listeners

listener.actionPerformed(event);

 Listener sets text of text field

textField.setText("Hello, World!");

 Ch4/action1/ActionTest.java

Constructing Related Actions


 Write helper method that constructs objects
 Pass variable information as parameters
 Declare parameters final

public static ActionListener createGreetingButtonListener(


final String message)
{
return new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
textField.setText(message);
}
};
}

Timers
 Supply delay, action listener
ActionListener listener = ...;
final int DELAY = 1000; // 1000 millisec = 1 sec

73
Timer t = new Timer(DELAY, listener);
t.start();
 Action listener called when delay elapsed
 Ch4/timer/TimerTest.java

Defining a New Interface Type


 Use timer to move car shapes
 Draw car with CarShape
 Two responsibilities:
o Draw shape
o Move shape
 Define new interface type MoveableShape

CRC Card for the MoveableShape Interface Type

Defining a New Interface Type


 Name the methods to conform to standard library

74
 public interface MoveableShape
{
void draw(Graphics2D g2);
void translate(int dx, int dy);
}
 CarShape class implements MoveableShape
public class CarShape implements MoveableShape
{
public void translate(int dx, int dy)
{ x += dx; y += dy; }
. . .
}

Implementing the Animation


 Label contains icon that draws shape
 Timer action moves shape, calls repaint on label
 Label needs Icon, we have MoveableShape
 Supply ShapeIcon adapter class
 ShapeIcon.paintIcon calls MoveableShape.draw

Implementing the Animation


 Ch4/animation/MoveableShape.java
 Ch4/animation/ShapeIcon.java
 Ch4/animation/AnimationTest.java
 Ch4/animation/CarShape.java

Implementing the Animation

75
76
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 5

Patterns and GUI Programming

Chapter Topics
 Iterators
 The Pattern Concept
 The OBSERVER Pattern
 Layout Managers and the STRATEGY Pattern
 Components, Containers, and the COMPOSITE Pattern
 Scroll Bars and the DECORATOR Pattern
 How to Recognize Patterns
 Putting Patterns to Work

List Iterators
LinkedList list = . . .;
ListIterator iterator = list.listIterator();
while (iterator.hasNext())
{

77
Object current = iterator.next();
. . .
}

 Why iterators?

Classical List Data Structure


 Traverse links directly

Link currentLink = list.head;


while (currentLink != null)
{
Object current = currentLink.data;
currentLink = currentLink.next;
}

 Exposes implementation
 Error-prone

High-Level View of Data Structures


 Queue

 Array with random access

 List
???

List with Cursor

78
for (list.reset(); list.hasNext(); list.next())
{
Object x = list.get();
. . .
}

 Disadvantage: Only one cursor per list


 Iterator is superior concept

The Pattern Concept


 History: Architectural Patterns
 Christopher Alexander
 Each pattern has
o a short name
o a brief description of the context
o a lengthy description of the problem
o a prescription for the solution

Short Passages Pattern

79
Short Passages Pattern
Context

"...Long, sterile corridors set the scene for everything bad about modern architecture..."

Problem

a lengthy description of the problem, including

 a depressing picture
 issues of light and furniture
 research about patient anxiety in hospitals
 research that suggests that corridors over 50 ft are considered uncomfortable

Short Passages Pattern


Solution

Keep passages short. Make them as much like rooms as possible, with carpets or wood on
the floor, furniture, bookshelves, beautiful windows. Make them generous in shape and
always give them plenty of light; the best corridors and passages of all are those which
have windows along an entire wall.

80
Iterator Pattern
Context

1. An aggregate object contains element objects


2. Clients need access to the element objects
3. The aggregate object should not expose its internal structure
4. Multiple clients may want independent access

Iterator Pattern
Solution

1. Define an iterator that fetches one element at a time


2. Each iterator object keeps track of the position of the next element
3. If there are several aggregate/iterator variations, it is best if the aggregate and
iterator classes realize common interface types.

Iterator Pattern

81
Iterator Pattern
 Names in pattern are examples
 Names differ in each occurrence of pattern

Name in Design Pattern Actual Name (linked lists)


Aggregate List
ConcreteAggregate LinkedList
Iterator ListIterator
ConcreteIterator anonymous class implementing ListIterator
createIterator() listIterator()
next() next()
isDone() opposite of hasNext()
currentItem() return value of hasNext()

Model/View/Controller
 Some programs have multiple editable views
 Example: HTML Editor
o WYSIWYG view
o structure view
o source view
 Editing one view updates the other
 Updates seem instantaneous

82
Model/View/Controller

Model/View/Controller
 Model: data structure, no visual representation
 Views: visual representations
 Controllers: user interaction

Model/View/Controller
 Views/controllers update model
 Model tells views that data has changed
 Views redraw themselves

Model/View/Controller

83
Observer Pattern
 Model notifies views when something interesting happens
 Button notifies action listeners when something interesting happens
 Views attach themselves to model in order to be notified
 Action listeners attach themselves to button in order to be notified
 Generalize: Observers attach themselves to subject

Observer Pattern
Context

1. An object, called the subject, is source of events


2. One or more observer objects want to be notified when such an event occurs.

Solution

1. Define an observer interface type. All concrete observers implement it.


2. The subject maintains a collection of observers.
3. The subject supplies methods for attaching and detaching observers.
4. Whenever an event occurs, the subject notifies all observers.

Observer Pattern

84
Names in Observer Pattern
Name in Design Pattern Actual Name (Swing buttons)
Subject JButton

Observer ActionListener

ConcreteObserver the class that implements the ActionListener interface type


attach() addActionListener()

notify() actionPerformed()

Layout Managers
 User interfaces made up of components
 Components placed in containers
 Container needs to arrange components
 Swing doesn't use hard-coded pixel coordinates
 Advantages:
o Can switch "look and feel"
o Can internationalize strings
 Layout manager controls arrangement

Layout Managers
 FlowLayout: left to right, start new row when full
 BoxLayout: left to right or top to bottom
 BorderLayout: 5 areas, Center, North, South, East, West
 GridLayout: grid, all components have same size
 GridBagLayout: complex, like HTML table

85
Layout Managers

Layout Managers
 Set layout manager
JPanel keyPanel = new JPanel();
keyPanel.setLayout(new GridLayout(4, 3));
 Add components
for (int i = 0; i < 12; i++)
keyPanel.add(button[i]);

Layout Managers

86
Voice Mail System GUI
 Same backend as text-based system
 Only Telephone class changes
 Buttons for keypad
 Text areas for microphone, speaker

Voice Mail System GUI

87
88
Voice Mail System GUI
 Arrange keys in panel with GridLayout:

JPanel keyPanel = new JPanel();


keyPanel.setLayout(new GridLayout(4, 3));
for (int i = 0; i < 12; i++)
{
JButton keyButton = new JButton(...);
keyPanel.add(keyButton);

89
keyButton.addActionListener(...);
}

Voice Mail System GUI


 Panel with BorderLayout for microphone

JPanel speakerPanel = new JPanel();


speakerPanel.setLayout(new BorderLayout());
speakerPanel.add(new JLabel("Speaker:"), BorderLayout.NORTH);
speakerField = new JTextArea(10, 25);
speakerPanel.add(speakerField, BorderLayout.CENTER);

Voice Mail System GUI


 Put speaker, keypads, and microphone panel into content pane
 Content pane already has BorderLayout
 Ch5/mailgui/Telephone.java

90
Custom Layout Manager
 Form layout
 Odd-numbered components right aligned
 Even-numbered components left aligned
 Implement LayoutManager interface type

The LayoutManager Interface Type


public interface LayoutManager
{
void layoutContainer(Container parent);

91
Dimension minimumLayoutSize(Container parent);
Dimension preferredLayoutSize(Container parent);
void addLayoutComponent(String name, Component comp);
void removeLayoutComponent(Component comp);
}

Form Layout
 Ch5/layout/FormLayout.java
 Ch5/layout/FormLayoutTest.java
 Note: Can use GridBagLayout to achieve the same effect

Strategy Pattern
 Pluggable strategy for layout management
 Layout manager object responsible for executing concrete strategy
 Generalizes to Strategy Design Pattern
 Other manifestation: Comparators

Comparator comp = new CountryComparatorByName();


Collections.sort(countries, comp);

Strategy Pattern
Context

1. A class can benefit from different variants for an algorithm


2. Clients sometimes want to replace standard algorithms with custom versions

Solution

1. Define an interface type that is an abstraction for the algorithm


2. Actual strategy classes realize this interface type.
3. Clients can supply strategy objects
4. Whenever the algorithm needs to be executed, the context class calls the
appropriate methods of the strategy object

Strategy Pattern

92
Strategy Pattern: Layout Management
Name in Design Pattern Actual Name (layout management)
Context Container
Strategy LayoutManager
ConcreteStrategy a layout manager such as BorderLayout
doWork() a method such as layoutContainer

Strategy Pattern: Sorting


Name in Design Pattern Actual Name (sorting)
Context Collections
Strategy Comparator
ConcreteStrategy a class that implements Comparator
doWork() compare

Containers and Components


 Containers collect GUI components
 Sometimes, want to add a container to another container
 Container should be a component
 Composite design pattern
 Composite method typically invoke component methods
 E.g. Container.getPreferredSize invokes getPreferredSize of components

93
Composite Pattern
Context

1. Primitive objects can be combined to composite objects


2. Clients treat a composite object as a primitive object

Solution

1. Define an interface type that is an abstraction for the primitive objects


2. Composite object collects primitive objects
3. Composite and primitive classes implement same interface type.
4. When implementing a method from the interface type, the composite class applies
the method to its primitive objects and combines the results

Composite Pattern

Composite Pattern
Name in Design Pattern Actual Name (AWT components)
Primitive Component
Composite Container
Leaf a component without children (e.g. JButton)
method() a method of Component (e.g. getPreferredSize)

Scroll Bars
 Scroll bars can be attached to components
 Approach #1: Component class can turn on scroll bars

94
 Approach #2: Scroll bars can surround component

JScrollPane pane = new JScrollPane(component);

 Swing uses approach #2


 JScrollPane is again a component

Scroll Bars

Decorator Pattern
Context

1. Component objects can be decorated (visually or behaviorally enhanced)


2. The decorated object can be used in the same way as the undecorated object
3. The component class does not want to take on the responsibility of the decoration
4. There may be an open-ended set of possible decorations

Decorator Pattern
Solution

1. Define an interface type that is an abstraction for the component

95
2. Concrete component classes realize this interface type.
3. Decorator classes also realize this interface type.
4. A decorator object manages the component object that it decorates
5. When implementing a method from the component interface type, the decorator
class applies the method to the decorated component and combines the result with
the effect of the decoration.

Decorator Pattern

Decorator Pattern: Scroll Bars


Name in Design Pattern Actual Name (scroll bars)
Component Component
ConcreteComponent JTextArea
Decorator JScrollPane
method() a method of Component (e.g. paint)

Streams
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader console = new BufferedReader(reader);

 BufferedReader takes a Reader and adds buffering


 Result is another Reader: Decorator pattern
 Many other decorators in stream library, e.g. PrintWriter

Decorator Pattern: Input Streams


Name in Design Pattern Actual Name (input streams)
Component Reader
ConcreteComponent InputStreamReader

96
Decorator BufferedReader
method() read

How to Recognize Patterns


 Look at the intent of the pattern
 E.g. COMPOSITE has different intent than DECORATOR
 Remember common uses (e.g. STRATEGY for layout managers)
 Not everything that is strategic is an example of STRATEGY pattern
 Use context and solution as "litmus test"

Litmus Test
 Can add border to Swing component

Border b = new EtchedBorder()


component.setBorder(b);

 Undeniably decorative
 Is it an example of DECORATOR?

Litmus Test
1. Component objects can be decorated (visually or behaviorally enhanced)
PASS
2. The decorated object can be used in the same way as the undecorated object
PASS
3. The component class does not want to take on the responsibility of the decoration
FAIL--the component class has setBorder method
4. There may be an open-ended set of possible decorations

Putting Patterns to Work


 Invoice contains line items
 Line item has description, price

97
 Interface type LineItem:
Ch5/invoice/LineItem.java
 Product is a concrete class that implements this interface:
Ch5/invoice/Product.java

Bundles
 Bundle = set of related items with description+price
 E.g. stereo system with tuner, amplifier, CD player + speakers
 A bundle has line items
 A bundle is a line item
 COMPOSITE pattern
 Ch5/invoice/Bundle.java (look at getPrice)

Bundles

Discounted Items
 Store may give discount for an item
 Discounted item is again an item
 DECORATOR pattern
 Ch5/invoice/DiscountedItem.java (look at getPrice)
 Alternative design: add discount to LineItem

Discounted Items

98
Model/View Separation
 GUI has commands to add items to invoice
 GUI displays invoice
 Decouple input from display
 Display wants to know when invoice is modified
 Display doesn't care which command modified invoice
 OBSERVER pattern

Change Listeners
 Use standard ChangeListener interface type
public interface ChangeListener
{
void stateChanged(ChangeEvent event);
}
 Invoice collects ArrayList of change listeners
 When the invoice changes, it notifies all listeners:
ChangeEvent event = new ChangeEvent(this);
for (int i = 0; i < listeners.size(); i++)
{
ChangeListener listener =
(ChangeListener)listeners.get(i);
listener.stateChanged(event);
}

Change Listeners
 Display adds itself as a change listener to the invoice
 Display updates itself when invoice object changes state

99
final Invoice invoice = new Invoice();
final JTextArea textArea = new JTextArea(20, 40);
ChangeListener listener = new
ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
textArea.setText(...);
}
};

Observing the Invoice

Iterating Through Invoice Items


 Invoice collect line items
 Clients need to iterate over line items
 Don't want to expose ArrayList
 May change (e.g. if storing invoices in database)
 ITERATOR pattern

Iterators
 Use standard Iterator interface type
public interface Iterator
{
boolean hasNext();
Object next();
void remove();
}

100
 remove is "optional operation" (see ch. 8)
 implement to throw UnsupportedException
 implement hasNext/next manually to show inner workings
 Ch5/invoice/Invoice.java

Iterators

Formatting Invoices
 Simple format: dump into text area
 May not be good enough,
 E.g. HTML tags for display in browser
 Want to allow for multiple formatting algorithms
 STRATEGY pattern

Formatting Invoices
 ch5/invoice/InvoiceFormatter.java
 ch5/invoice/SimpleFormatter.java
 ch5/invoice/InvoiceTest.java

Formatting Invoices

101
Formatting Invoices

102
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 6

Inheritance and Abstract Classes

Chapter Topics
 The Concept of Inheritance
 Graphics Programming with Inheritance
 Abstract Classes
 The TEMPLATE METHOD Pattern
 Protected Interfaces
 The Hierarchy of Swing Components
 The Hierarchy of Standard Geometrical Shapes
 The Hierarchy of Exception Classes
 When Not to Use Inheritance

Modeling Specialization
 Start with simple Employee class
public class Employee

103
{
public Employee(String aName) { name = aName; }
public void setSalary(double aSalary) { salary =
aSalary; }
public String getName() { return name; }
public double getSalary() { return salary; }

private String name;


private double salary;
}
 Manager is a subclass

Modeling Specialization
 Manager class adds new method: setBonus
 Manager class overrides existing method: getSalary
 Adds salary and bonus
 public class Manager extends Employee
{
public Manager(String aName) { ... }
public void setBonus(double aBonus) { bonus =
aBonus; } // new method
public double getSalary() { ... } // overrides
Employee method

private double bonus; // new field


}

Modeling Specialization

104
Manager Methods and Fields
 methods setSalary, getname (inherited from Employee)
 method getSalary (overridden in Manager)
 method setBonus (defined in Manager)
 fields name and salary (defined in Employee)
 field bonus (defined in Manager)

The Super/Sub Terminology


 Why is Manager a subclass?
 Isn't a Manager superior?
 Doesn't a Manager object have more fields?
 The set of managers is a subset of the set of employees

The Super/Sub Terminology

105
Inheritance Hierarchies
 Real world: Hierarchies describe general/specific relationships
o General concept at root of tree
o More specific concepts are children
 Programming: Inheritance hierarchy
o General superclass at root of tree
o More specific subclasses are children

Inheritance Hierarchies

The Substitution Principle


 Formulated by Barbara Liskov
 You can use a subclass object whenever a superclass object is expected

106
 Example:
Employee e;
...
System.out.println("salary=" + e.getSalary());
 Can set e to Manager reference
 Polymorphism: Correct getSalary method is invoked

Invoking Superclass Methods


 Can't access private fields of superclass
public class Manager extends Employee
{
public double getSalary()
{
return salary + bonus; // ERROR--private field
}
...
}
 Be careful when calling superclass method
public double getSalary()
{
return getSalary() + bonus; // ERROR--recursive
call
}

Invoking Superclass Methods


 Use super keyword
public double getSalary()
{
return super.getSalary() + bonus;
}
 super is not a reference
 super turns off polymorphic call mechanism

Invoking Superclass Constructors


 Use super keyword in subclass constructor:
public Manager(String aName)
{
super(aName); // calls superclass constructor
bonus = 0;
}
 Call to super must be first statement in subclass constructor

107
 If subclass constructor doesn't call super, superclass must have constructor
without parameters

Preconditions
 Precondition of redefined method at most as strong
 public class Employee
{
/**
Sets the employee salary to a given value.
@param aSalary the new salary
@precondition aSalary > 0
*/
public void setSalary(double aSalary) { ... }
}
 Can we redefine Manager.setSalary with precondition
salary > 100000?
 No--Could be defeated:

Manager m = new Manager();


Employee e = m;
e.setSalary(50000);

Postconditions, Visibility, Exceptions


 Postcondition of redefined method at least as strong
 Example: Employee.setSalary promises not to decrease salary
 Then Manager.setSalary must fulfill postcondition
 Redefined method cannot be more private.
(Common error: omit public when redefining)
 Redefined method cannot throw more checked exceptions

Graphic Programming with Inheritance


 Chapter 4: Create drawings by by implementing Icon interface type
 Now: Form subclass of JPanel
public class MyPanel extends JPanel
{
public void paintComponent(Graphics g)
{
drawing instructions go here
}
...
}
 Advantage: Inherit behavior from JPanel
 Example: Can attach mouse listener to JPanel

108
Overriding paintComponent
 Draw a car:
public class MyPanel extends JPanel
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
car.draw(g2);
}
...
}
 Problem: Screen is corrupted when moving frame
 Remedy: call super.paintComponent(g)

Overriding paintComponent

Mouse Listeners
 Attach mouse listener to component
 Can listen to mouse events (clicks) or mouse motion events

public interface MouseListener


{
void mouseClicked(MouseEvent event);
void mousePressed(MouseEvent event);
void mouseReleased(MouseEvent event);
void mouseEntered(MouseEvent event);
void mouseExited(MouseEvent event);
}

109
public interface MouseMotionListener
{
void mouseMoved(MouseEvent event);
void mouseDragged(MouseEvent event);
}

Mouse Adapters
 What if you just want to listen to mousePressed?
 Extend MouseAdapter

public class MouseAdapter implements MouseListener


{
public void mouseClicked(MouseEvent event) {}
public void mousePressed(MouseEvent event) {}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
}

 Component constructor adds listener:

addMouseListener(new
MouseAdapter()
{
public void mousePressed(MouseEvent event)
{
mouse action goes here
}
});

Car Mover Program


 Use the mouse to drag a car shape
 Car panel has mouse + mouse motion listeners
 mousePressed remembers point of mouse press
 mouseDragged translates car shape
 Ch6/car/CarPanel.java
 Ch6/car/CarMover.java
 Ch6/car/CarShape.java

Car Mover Program

110
Scene Editor
 Draws various shapes
 User can add, delete, move shapes
 User selects shape with mouse
 Selected shape is highlighted (filled in)

Scene Editor

The SceneShape Interface Type


 keep track of selection state
 draw plain or selected shape
 move shape
 hit testing: is a point (e.g. mouse position) inside?

111
The SceneShape Interface Type

The SceneShape Interface Type


public interface SceneShape
{
void setSelected(boolean b);
boolean isSelected();
void draw(Graphics2D g2);
void drawSelection(Graphics2D g2);
void translate(double dx, double dy);
boolean contains(Point2D aPoint);
}

CarShape and HouseShape Classes


public class CarShape implements SceneShape
{
...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}

public class HouseShape implements SceneShape


{
...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}

Abstract Classes

112
 Factor out common behavior
(setSelected, isSelected)
 Subclasses inherit common behavior
 Some methods still undefined
(draw, drawSelection, translate, contains)

public class SelectableShape implements Item


{
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}

Abstract Classes

Abstract Classes
 SelectableShape doesn't define all SceneShape methods
 It's abstract
 public abstract class SelectableShape implements SceneShape
 HouseShape and CarShape are concrete
 Can't instantiate abstract class:

SelectableShape s = new SelectableShape(); // NO

113
 Ok to have variables of abstract class type:

SelectableShape s = new HouseShape(); // OK

Abstract Classes and Interface Types


 Abstract classes can have fields
 Interface types can only have constants (public static final)
 Abstract classes can define methods
 Interface types can only declare methods
 A class can implement any number of interface types
 In Java, a class can extend only one other class

Scene Editor
 Mouse listener selects/unselects item
 Mouse motion listener drags item
 Remove button removes selected items
 Ch6/scene1/ScenePanel.java
 Ch6/scene1/SceneEditor.java
 Ch6/scene1/HouseShape.java

Uniform Highlighting Technique


 Old approach: each shape draws its selection state
 Inconsistent
 Better approach: shift, draw, shift, draw, restore to original position
 Define in SelectableShape
public void drawSelection(Graphics2D g2)
{
translate(1, 1);
draw(g2);
translate(1, 1);
draw(g2);
translate(-2, -2);
}

Uniform Highlighting Technique

114
Template Method
 drawSelection calls draw
 Must declare draw in SelectableShape
 No implementation at that level!
 Declare as abstract method
public abstract void draw(Graphics2D g2)
 Defined in CarShape, HouseShape
 drawSelection method calls draw, translate
 drawSelection doesn't know which methods--polymorphism
 drawSelection is a template method
 Ch6/scene2/SelectableShape.java
 Ch6/scene2/HouseShape.java

TEMPLATE METHOD Pattern


Context

1. An algorithm is applicable for multiple types.


2. The algorithm can be broken down into primitive operations. The primitive
operations can be different for each type
3. The order of the primitive operations doesn't depend on the type

TEMPLATE METHOD Pattern


Solution

1. Define a superclass that has a method for the algorithm and abstract methods for
the primitive operations.

115
2. Implement the algorithm to call the primitive operations in the appropriate order.
3. Do not define the primitive operations in the superclass, or define them to have
appropriate default behavior.
4. Each subclass defines the primitive operations but not the algorithm.

TEMPLATE METHOD Pattern

TEMPLATE METHOD Pattern


Name in Design Pattern Actual Name (Selectable shapes)
AbstractClass SelectableShape
ConcreteClass CarShape, HouseShape
templateMethod() drawSelection
primitiveOp1(), primitiveOp2() translate, draw

Compound Shapes
 GeneralPath: sequence of shapes

GeneralPath path = new GeneralPath();


path.append(new Rectangle(...), false);
path.append(new Triangle(...), false);
g2.draw(path);

 Advantage: Containment test is free


path.contains(aPoint);
 Ch6/scene3/CompoundShape.java
 Ch6/scene3/HouseShape.java

116
Compound Shapes

Access to Superclass Features


 Why does the HouseShape constructor call add?

public HouseShape()
{
add(new Rectangle(...));
add(new Triangle(...));
}

 Why not just


path.append(new Rectangle(...));
 HouseShape inherits path field
 HouseShape can't access path
 path is private to superclass

117
Protected Access
 Make CompoundShape.add method protected
 Protects HouseShape: other classes can't add graffiti
 Protected features can be accessed by subclass methods...
 ...and by methods in the same package
 Bad idea to make fields protected
protected GeneralPath path; // DON'T
 Ok to make methods protected
protected void add(Shape s) // GOOD
 Protected interface separate from public interface

Hierarchy of Swing Components


 Base of hierarchy: Component
 Huge number of common methods:

int getWidth()
int getHeight()
Dimension getPreferredSize()
void setBackground(Color c)
. . .

 Most important subclass: Container

Hierarchy of Swing Components

118
Hierarchy of Swing Components
 History: First came AWT, Abstract Window Toolkit
 Used native components
 Subtle platform inconsistencies
 Write once, run anywhere ->
Write once, debug everywhere
 Swing paints components onto blank windows
 Supports multiple look and feel implementations

Look and Feel

Hierarchy of Swing Components


 Base of Swing components: JComponent
 Subclass of Container
 Some Swing components are containers
 Java has no multiple inheritance
 JLabel, JPanel, ... are subclasses of JComponent
 Intermediate classes AbstractButton, JTextComponent

Hierarchy of Geometrical Shapes


 First version of Java: few shapes, integer coordinates

Point
Rectangle
Polygon

119
 Java 2: sophisticated shapes, floating-point coordinates

Point2D
Rectangle2D
RoundRectangle2D
Line2D
Ellipse2D
Arc2D
QuadCurve2D
CubicCurve2D
GeneralPath
Area

 All but Point2D implement Shape interface type

Hierarchy of Geometrical Shapes

Rectangular Shapes
 Subclasses of RectangularShape:

Rectangle2D
RoundRectangle2D
Ellipse2D
Arc2D

 RectangularShape has useful methods

getCenterX/getCenterY
getMinX/getMinY
getMaxX/getMaxY

120
getWidth/getHeight
setFrameFromCenter/setFrameFromDiagonal

Float/Double Classes
 Each class has two subclasses, e.g.

Rectangle2D.Double
Rectangle2D.Float

 Are also inner classes!


(Just to avoid even longer class names)
 Implementations have double/float fields
 Most methods have double parameters/return values

Float/Double Classes

Float/Double Classes
public class Rectangle2D
{
public static class Float extends Rectangle2D
{
public double getX() { return x; }
public double getY() { return y; }
public double getWidth() { return width; }
public double getHeight() { return height;}
public void setRect(float x, float y, float w, float h)
{
this.x = x; this.y = y;
this.width = w; this.height = h;
}
public void setRect(double x, double y,
double w, double h)
{

121
this.x = (float)x; this.y = (float)y;
this.width = (float)w; this.height = (float)h;
}
...
public float x;
public float y;
public float width;
public float height;
}
. . .

Float/Double Classes
. . .
public static class Double extends Rectangle2D
public double getX() { return x; }
public double getY() { return y; }
public double getWidth() { return width; }
public double getHeight() { return height;}
public void setRect(double x, double y,
double w, double h)
{
this.x = x; this.y = y;
this.width = w; this.height = h;
}
...
public double x;
public double y;
public double width;
public double height;
}
...
}

Float/Double Classes
 Rectangle2D class has no instance variables
 Template Method Pattern at work:

public boolean contains(double x, double y)


{
double x0 = getX();
double y0 = getY();
return x >= x0 && y >= y0 &&
x < x0 + getWidth() &&
y < y0 + getHeight();
}

 No need to use inner class after construction


Rectangle2D rect
= new Rectangle2D.Double(5, 10, 20, 30);

122
TEMPLATE METHOD Pattern
Name in Design Pattern Actual Name (Rectangles)
AbstractClass Rectangle
ConcreteClass Rectangle2D.Double
templateMethod() contains
primitiveOpn() getX, getY, getWidth, getHeight

Hierarchy of Exception Classes


 Base of hierarchy: Throwable
 Two subclasses: Error, Exception
 Subclasses of Error: fatal
(out of memory, assertion failure)
 Subclasses of Exception:
o Lots of checked exceptions
(I/O, class not found)
o RuntimeException--its subclasses are unchecked
(null pointer, index out of bounds)

Hierarchy of Exception Classes

123
Catching Exceptions
 Can have multiple catch clauses:

try
{
code that may throw exceptions
}
catch (ExceptionType1 exception1)
{
handler for ExceptionType1
}
catch (ExceptionType2 exception1)
{
handler for ExceptionType2
}
. . .

 Can catch by superclass:


catch (IOException exception)
catches FileNotFoundException

Defining Exception Classes


 Decide exception should be checked
 Subclass Exception or RuntimeException
 Provide two constructors

public class IllegalFormatException extends Exception


{
public IllegalFormatException() {}
public IllegalFormatException(String reason)
{ super(reason); }
}

 Throw exception when needed:


throw new IllegalFormatException("number expected");

When Not to Use Inheritance


 From a tutorial for a C++ compiler:

public class Point


{
public Point(int anX, int aY) { ... }
public void translate(int dx, int dy) { ... }
private int x;
private int y;
}

124
public class Circle extends Point // DON'T
{
public Circle(Point center, int radius) { ... }
public void draw(Graphics g) { ... }
private int radius;
}

When Not to Use Inheritance


 Huh? A circle isn't a point.
 By accident, inherited translate works for circles
 Same tutorial makes Rectangle a subclass of Point:

public class Rectangle extends Point // DON'T


{
public Rectangle(Point corner1, Point corner2) { ... }
public void draw(Graphics g) { ... }
public void translate(int dx, int dy) { ... }
private Point other;
}

When Not to Use Inheritance


 That's even weirder:

public void translate(double dx, double dy)


{
super.translate(dx, dy);
other.translate(dx, dy);
}

 Why did they do that?


 Wanted to avoid abstract class Shape
 Remedy: Use aggregation.
 Circle, Rectangle classes have points

When Not to Use Inheritance


 Java standard library:

public class Stack extends Vector // DON'T


{
Object pop() { ... }
void push(Object item) { ... }
...
}

 Bad idea: Inherit all Vector methods


 Can insert/remove in the middle of the stack

125
 Remedy: Use aggregation

public class Stack


{
...
private Vector elements;
}

126
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 7

The Java Object Model

Chapter Topics
 The Java Type System
 Type Inquiry
 The Object Class
 Shallow and Deep Copy
 Serialization
 Reflection
 The Java Beans Component Model

Types
 Type: set of values and the operations that can be applied to the values
 Strongly typed language: compiler and run-time system check that no operation
can execute that violates type system rules

127
 Compile-time check
Employee e = new Employee();
e.clear(); // ERROR
 Run-time check:
e = null;
e.setSalary(20000); // ERROR

Java Types
 Primitive types:
int short long byte
char float double boolean
 Class types
 Interface types
 Array types
 The null type
 Note: void is not a type

Exercise: What kind of type?


 int
 Rectangle
 Shape
 String[]
 double[][]

Java Values
 value of primitive type
 reference to object of class type
 reference to array
 null
 Note: Can't have value of interface type

Exercise: What kind of value?


 13
 new Rectangle(5, 10, 20, 30);
 "Hello"
 new int[] { 2, 3, 5, 7, 11, 13 }
 null

Subtype Relationship
S is a subtype of T if

128
 S and T are the same type
 S and T are both class types, and T is a direct or indirect superclass of S
 S is a class type, T is an interface type, and S or one of its superclasses
implements T
 S and T are both interface types, and T is a direct or indirect superinterface of S
 S and T are both array types, and the component type of S is a subtype of the
component type of T
 S is not a primitive type and T is the type Object
 S is an array type and T is Cloneable or Serializable
 S is the null type and T is not a primitive type

Subtype Examples
 Container is a subtype of Component
 JButton is a subtype of Component
 FlowLayout is a subtype of LayoutManager
 ListIterator is a subtype of Iterator
 Rectangle[] is a subtype of Shape[]
 int[] is a subtype of Object
 int is not a subtype of long
 long is not a subtype of int
 int[] is not a subtype of Object[]

Subtype Examples

129
The ArrayStoreException
 Rectangle[] is a subtype of Shape[]
 Can assign Rectangle[] value to Shape[] variable:

Rectangle[] r = new Rectangle[10];


Shape[] s = r;

 Both r and s are references to the same array


 That array holds rectangles
 The assignment
s[0] = new Polygon();
compiles
 Throws an ArrayStoreException at runtime
 Each array remembers its component type

Array References

130
Wrapper Classes
 Primitive types aren't classes
 Use wrappers when objects are expected
 Wrapper for each type:

Integer Short Long Byte


Character Float Double Boolean

 Example: ArrayList

ArrayList numbers = new ArrayList();


numbers.add(new Integer(13));
int n = ((Integer)numbers.get(0)).intValue();

Enumerated Types
 Finite set of values
 Example: { SMALL, MEDIUM, LARGE }
 Java has no syntax for enumerated types
 Can fake them with integer constants
public static final int SMALL = 1;
public static final int MEDIUM = 2;
public static final int LARGE = 3;
 Not typesafe
int size = LARGE;
size++;

Typesafe Enumerations

131
 Class with fixed number of instances
public class Size
{
private Size(String name) { this.name = name; }
private String name;
public static final Size SMALL = new Size("SMALL");
public static final Size MEDIUM = new
Size("MEDIUM");
public static final Size LARGE = new Size("LARGE");
}
 Private constructor!
 String field not necessary (but convenient for toString, serialization)
 Typical use:
Size imageSize = Size.MEDIUM;
if (imageSize == Size.SMALL) . . .

Type Inquiry
 Test whether e is a Shape:
if (e instanceof Shape) . . .
 Common before casts:
Shape s = (Shape) e;
 Don't know exact type of e
 Could be any class implementing Shape
 If e is null, test returns false (no exception)

The Class Class


 getClass method gets class of any object
 Returns object of type Class
 Class object describes a type

Object e = new Rectangle();


Class c = e.getClass();
System.out.println(c.getName()); // prints java.awt.Rectangle

 Class.forName method yields Class object:


Class c = Class.forName(java.awt.Rectangle);
 .class suffix yields Class object:
Class c = Rectangle.class; // java.awt prefix not needed
 Class is a misnomer: int.class, void.class,Shape.class

An Employee Object vs. the Employee.class


Object

132
Type Inquiry
 Test whether e is a Rectangle:
if (e.getClass() == Rectangle.class) . . .
 Ok to use ==
 A unique Class object for every class
 Test fails for subclasses
 Use instanceof to test for subtypes:
if (x instanceof Rectangle) . . .

Array Types
 Can apply getClass to an array
 Returned object describes an array type

double[] a = new double[10];


Class c = a.getClass();
if (c.isArray())
System.out.println(c.getComponentType());
// prints double

 getName produces strange names for array types

[D for double[])
[[java.lang.String; for String[][]

Object: The Cosmic Superclass

133
 All classes extend Object
 Most useful methods:
o String toString()
o boolean equals(Object otherObject)
o Object clone()
o int hashCode()

The toString Method


 Returns a string representation of the object
 Useful for debugging
 Example: Rectangle.toString returns something like
java.awt.Rectangle[x=5,y=10,width=20,height=30]
 toString used by concatenation operator
 aString + anObject
means
aString + anObject.toString()
 Object.toString prints class name and object address
System.out.println(System.out)
yields
java.io.PrintStream@d2460bf
 Implementor of PrintStream didn't override toString:

Overriding the toString Method


 Format all fields:

public class Employee


{
public String toString()
{
return getClass().getName()
+ "[name=" + name
+ ",salary=" + salary
+ "]";
}
...
}

 Typical string:

Employee[name=Harry Hacker,salary=35000]

Overriding toString in Subclass


 Format superclass first
 public class Manager extends Employee
{
public String toString()

134
{
return super.toString()
+ "[department=" + department + "]";
}
...
}

 Typical string

Manager[name=Dolly Dollar,salary=100000][department=Finance]

 Note that superclass reports actual class name

The equals Method


 equals tests for equal contents
 == tests for equal location
 Used in many standard library methods
 Example: ArrayList.indexOf

/**
Searches for the first occurrence of the given argument,
testing for equality using the equals method.
@param elem an object.
@return the index of the first occurrence
of the argument in this list; returns -1 if
the object is not found.
*/
public int indexOf(Object elem)
{
if (elem == null)
{
for (int i = 0; i < size; i++)
if (elementData[i] == null) return i;
}
else
{
for (int i = 0; i < size; i++)
if (elem.equals(elementData[i])) return i;
}
return -1;
}

Overriding the equals Method


 Notion of equality depends on class
 Common definition: compare all fields

public class Employee


{
public boolean equals(Object otherObject)

135
// not complete--see below
{
Employee other = (Employee)otherObject;
return name.equals(other.name)
&& salary == other.salary;
}
...
}

 Must cast the Object parameter to subclass


 Use == for primitive types, equals for object fields

Overriding equals in Subclass


 Call equals on superclass

public class Manager


{
public boolean equals(Object otherObject)
{
Manager other = (Manager)otherObject;
return super.equals(other)
&& department.equals(other.department);
}
}

Not all equals Methods are Simple


 Two sets are equal if they have the same elements in some order

public boolean equals(Object o)


{
if (o == this) return true;
if (!(o instanceof Set)) return false;
Collection c = (Collection) o;
if (c.size() != size()) return false;
return containsAll(c);
}

The Object.equalsMethod
 Object.equals tests for identity:

public class Object


{
public boolean equals(Object obj)
{
return this == obj;
}
...
}

136
 Override equals if you don't want to inherit that behavior

Requirements for equals Method


 reflexive: x.equals(x)
 symmetric: x.equals(y) if and only if y.equals(x)
 transitive: if x.equals(y) and y.equals(z), then x.equals(z)
 x.equals(null) must return false

Fixing Employee.equals
 Violates two rules
 Add test for null:
if (otherObject == null) return false
 What happens if otherObject not an Employee
 Should return false (because of symmetry)
 Common error: use of instanceof
if (!(otherObject instanceof Employee)) return false;
// don't do this for non-final classes
 Violates symmetry: Suppose e, m have same name, salary
e.equals(m) is true (because m instanceof Employee)
m.equals(e) is false (because e isn't an instance of Manager)
 Remedy: Test for class equality
if (getClass() != otherObject.getClass()) return false;

The Perfect equals Method


 Start with these three tests:

public boolean equals(Object otherObject)


{
if (this == otherObject) return true;
if (otherObject == null) return false;
if (getClass() != otherObject.getClass()) return false;
...
}

 First test is an optimization

Hashing
 hashCode method used in HashMap, HashSet
 Computes an int from an object
 Example: hash code of String
int h = 0;

137
for (int i = 0; i < s.length(); i++)
h = 31 * h + s.charAt(i);
 Hash code of "eat" is 100184
 Hash code of "tea" is 114704

Hashing
 Must be compatible with equals:
if x.equals(y), then x.hashCode() == y.hashCode()
 Object.hashCode hashes memory address
 NOT compatible with redefined equals
 Remedy: Hash all fields and combine codes:

public class Employee


{
public int hashCode()
{
return name.hashCode()
+ new Double(salary).hashCode();
}
...
}

Shallow and Deep Copy


 Assignment (copy = e) makes shallow copy
 Clone to make deep copy
 Employee cloned = (Employee)e.clone();

Cloning

138
Cloning
 Object.clone makes new object and copies all fields
 Cloning is subtle
 Object.clone is protected
 Subclass must redefine clone to be public

public class Employee


{
public Object clone()
{
return super.clone(); // not complete
}
...
}

The Cloneable Interface


 Object.clone is nervous about cloning
 Will only clone objects that implement Cloneable interface

public interface Cloneable


{
}

 Interface has no methods!


 Tagging interface--used in test
if x implements Cloneable
 Object.clone throws CloneNotSupportedException
 A checked exception

The clone Method


public class Employee
implements Cloneable
{
public Object clone()
{
try
{
return super.clone();
}
catch(CloneNotSupportedException e)
{
return null; // won't happen
}
}
...
}

139
Shallow Cloning
 clone makes a shallow copy
 Instance fields aren't cloned

Deep Cloning
 Why doesn't clone make a deep copy?
Wouldn't work for cyclic data structures
 Not a problem for immutable fields
 You must clone mutable fields

public class Employee


implements Cloneable
{
public Object clone()
{
try
{
Employee cloned = (Employee)super.clone();
cloned.hireDate = (Date)hiredate.clone();
return cloned;
}
catch(CloneNotSupportedException e)
{
return null; // won't happen
}
}
...
}

Deep Cloning

140
Cloning and Inheritance
 Object.clone is paranoid
o clone is protected
o clone only clones Cloneable objects
o clone throws checked exception
 You don't have that luxury
 Manager.clone must be defined if Manager adds mutable fields
 Rule of thumb: if you extend a class that defines clone, redefine clone
 Lesson to learn: Tagging interfaces are inherited. Use them only to tag properties
that inherit

Serialization
 Save collection of objects to stream

Employee[] staff = new Employee[2];


staff.add(new Employee(...));
staff.add(new Employee(...));

 Construct ObjectOutputStream:

ObjectOutputStream out
= new ObjectOutputStream(
new FileOutputStream("staff.dat"));

141
 Save the array and close the stream

out.writeObject(staff);
out.close();

Serialization
 The array and all of its objects and their dependent objects are saved
 Employee doesn't have to define any method
 Needs to implement the Serializable interface
 Another tagging interface with no methods

How Serialization Works


 Each newly encountered object is saved
 Each object gets a serial number in the stream
 No object is saved twice
 Reference to already encountered object saved as "reference to #"

How Serialization Works

Serialing Unserializable Classes


 Some classes are not serializable
 Security? Anonymous classes? Programmer cluelessness?
 Example: Ellipse2D.Double
 How can we serialize Car?
 Suppress default serialization to avoid exception
 Mark with transient:
private transient Ellipse2D frontTire;

142
 Supply private (!) methods
private void writeObject(ObjectOutputStream out)
private void readObject(ObjectInputStream in)
 In these methods
o Call writeDefaultObject/readDefaultObject
o Manually save other data
 Ch7/serial/Car.java

Reflection
 Ability of running program to find out about its objects and classes
 Class object reveals
o superclass
o interfaces
o package
o names and types of fields
o names, parameter types, return types of methods
o parameter types of constructors

Reflection
 Class getSuperclass()
 Class[] getInterfaces()
 Package getPackage()
 Field[] getDeclaredFields()
 Constructor[] getDeclaredConstructors()
 Method[] getDeclaredMethods()

Enumerating Fields
 Print the names of all static fields of the Math class:

Field[] fields = Math.class.getDeclaredFields();


for (int i = 0; i < fields.length; i++)
if (Modifier.isStatic(fields[i].getModifiers()))
System.out.println(fields[i].getName());

Enumerating Constructors
 Print the names and parameter types of all Rectangle
constructors:

for (int i = 0; i < cons.length; i++)


{
Class[] params = cons[i].getParameterTypes();
System.out.print("Rectangle(");

143
for (int j = 0; j < params.length; j++)
{
if (j > 0) System.out.print(", ");
System.out.print(params[j].getName());
}
System.out.println(")");
}

 Yields

Rectangle()
Rectangle(java.awt.Rectangle)
Rectangle(int, int, int, int)
Rectangle(int, int)
Rectangle(java.awt.Point, java.awt.Dimension)
Rectangle(java.awt.Point)
Rectangle(java.awt.Dimension)

Getting A Single Method Descriptor


 Supply method name
 Supply array of parameter types
 Example: Get Rectangle.contains(int, int):

Method m = Rectangle.class.getDeclaredMethod(
"contains",
new Class[] { int.class, int.class });

 Example: Get default Rectangle constructor:

Constructor c = Rectangle.class.getDeclaredConstructor(
new Class[] {});

Invoking a Method
 Supply implicit parameter (null for static methods)
 Supply array of explicit parameter values
 Wrap primitive types
 Unwrap primitive return value
 Example: Call System.out.println("Hello, World") the hard way.

Method m = PrintStream.class.getDeclaredMethod(
"println",
new Class[] { String.class } );
m.invoke(System.out,
new Object[] { "Hello, World!" });

Inspecting Objects

144
 Can obtain object contents at runtime
 Useful for generic debugging tools
 Need to gain access to private fields

Class c = obj.getClass();
Field f = c.getDeclaredField(name);
f.setAccessible(true);

 Throws exception if security manager disallows access


 Access field value:

Object value = f.get(obj);


f.set(obj, value);

 Use wrappers for primitive types

Inspecting Objects
 Example: Peek inside string tokenizer
 Ch7/code/reflect2/FieldTest.java
 Output

int currentPosition=0
int newPosition=-1
int maxPosition=13
java.lang.String str=Hello, World!
java.lang.String delimiters=,
boolean retDelims=false
boolean delimsChanged=false
char maxDelimChar=,
---
int currentPosition=5
. . .

Inspecting Array Elements


 Use static methods of Array class
 Object value = Array.get(a, i);
Array.set(a, i, value);
 int n = Array.getLength(a);
 Construct new array:

Object a = Array.newInstance(type, length);

Components
 More functionality than a single class
 Reuse and customize in multiple contexts

145
 "Plug components together" to form applications
 Successful model: Visual Basic controls
o calendar
o graph
o database
o link to robot or instrument
 Componens composed into program inside builder environment

A Builder Environment

Java Beans
 Java component model
 Bean has
o methods (just like classes)
o properties
o events

Java Beans

146
A Calendar Bean

A Property Sheet
 Edit properties with property sheet

Facade Class
 Bean usually composed of multiple classes
 One class nominated as facade class

147
 Clients use only facade class methods

Facade Pattern
Context

1. A subsystem consists of multiple classes, making it complicated for clients to use


2. Implementor may want to change subsystem classes
3. Want to give a coherent entry point

Solution

1. Define a facade class that exposes all capabilities of the subsystem as methods
2. The facade methods delegate requests to the subsystem classes
3. The subsystem classes do not know about the facade class

Facade Pattern

Facade Pattern
Name in Design Pattern Actual Name (Beans)

148
Client Builder tool
Facade Main bean class with which the tool interacts
SubsystemClass Class used to implement bean functionality

Bean Properties
 Property = value that you can get and/or set
 Most properties are get-and-set
 Can also have get-only and set-only
 Property not the same as instance field
 Setter can set fields, then call repaint
 Getter can query database

Property Syntax
 Not Java :-(
 C#, JavaScript, Visual Basic
 b.propertyName = value
calls setter
 variable = b.propertyName
calls getter

Java Naming Conventions


 property = pair of methods
public X getPropertyName()
public void setPropertyName(X newValue)
 Replace propertyName with actual name
(e.g. getColor/setColor)
 Exception for boolean properties:
public boolean isPropertyName()
 Decapitalization hokus-pokus:
getColor -> color
getURL -> URL

Editing Beans in a Builder Tool


 Use wizard to make empty frame

149
Editing Beans in a Builder Tool
 Add button to frame
 Edit button with property sheet

150
Packaging a Bean
 Compile bean classes
Ch7/carbean1/CarBean.java
 Create manifest file
Ch7/carbean1/CarBean.mf
 Run JAR tool:
jar cvfm CarBean.jar CarBean.mf *.class
 Import JAR file into builder environment

Composing Beans
 Make new frame
 Add car bean, slider to frame
 Edit stateChanged event of slider
 Add handler code
carBean1.setX(jSlider1.getValue());
 Compile and run
 Move slider: the car moves

151
Composing Beans

Bean Information
 Builder environment loads beans
 Looks for get/set methods in facade class
 Can discover spurious properties
JButton: Object getTreeLock()
 Alternate mechanism: BeanInfo class
 Must have name FacadeClassNameBeanInfo
 E.g. HouseBeanBeanInfo

The BeanInfo Interface


Image getIcon(int iconKind)
BeanDescriptor getBeanDescriptor()
MethodDescriptor[] getMethodDescriptors()
PropertyDescriptor[] getPropertyDescriptors()
EventSetDescriptor[] getEventSetDescriptors()

152
int getDefaultEventIndex()
int getDefaultPropertyIndex()
BeanInfo[] getAdditionalBeanInfo()

Removing Spurious Properties


class MyBeanBeanInfo extends SimpleBeanInfo
{
public PropertyDescriptor[] getPropertyDescriptors()
{
try
{
return new PropertyDescriptor[]
{
new PropertyDescriptor("x", CarBean.class);
new PropertyDescriptor("y", CarBean.class);
};
}
catch (IntrospectionException exception)
{ return null; }
}
}

Property Editors
 Property sheet enumerates properties
 Allows user to edit property values
 How can one edit values of arbitrary types?
 Built-in editors for String, Color, etc
 Supply custom editor for your own types

Custom Property Editors


 Three kinds of editors
o Text
o Finite set of choices
o Arbitrary painting and editing
 Implement PropertyEditor interface
 Or extend PropertyEditorSupport class

Editing Text Properties


 Convert between your type and String
 Define two methods

public String getAsText()


public void setAsText(String s)

153
 Property sheet uses text field

Editing Choice Properties


 Your type has finite set of string choices
 E.g. DrawMode.DRAW, DrawMode.FILL
 String[] getTags() returns array of choices
 Also need to define getAsText/setAsText
 Property sheet uses combo box

Editing Arbitrary Properties


 Your type isn't easily editable as string
 E.g. Color
 Property editor pops up your edit dialog
o boolean supportsCustomEditor() must return true
o Component getCustomEditor() returns dialog
 Property editor can paint current value of your type
o boolean isPaintable() must return true
o void paintValue(Graphics g, Rectangle bounds) paints

Registering Property Editors


 Global setting

PropertyEditorManager.registerEditor(valueClass, editorClass)

 Per-bean setting
In bean info class:

PropertyDescriptor dimensionProperty = new PropertyDescriptor(


"dimension", CarBean.class);
dimensionProperty.setPropertyEditorClass(DimensionEditor.class);

Example: CarBean
 Ch7/carbean2/CarBean.java
 Ch7/carbean2/CarBeanBeanInfo.java
 Ch7/carbean2/DimensionEditor.java
 Ch7/carbean2/DrawMode.java
 Ch7/carbean2/DrawModeEditor.java
 Ch7/carbean2/CustomColorEditor.java

Example: CarBean

154
Implementing a Property Sheet
 Used for graph framework in chapter 8
 Form shows property names on left, editors on right

Implementing a Property Sheet


 Get bean info for class
 Get properties from bean info
 Obtain property getter/setter methods from property descriptor
 Use these methods to read and write property values
 Each editor is text field, combo box, or button with painted icon
 Clicking on button brings up dialog
 Ch7/propedit/PropertySheet.java
 Ch7/propedit/PropertySheetTest.java

155
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 8

Frameworks

Chapter Topics
 Frameworks
 Applets as a simple framework
 The collections framework
 A graph editor framework
 Enhancing the graph editor framework

Frameworks
 Set of cooperating classes
 Structures the essential mechanisms of a problem domain
 Example: Swing is a GUI framework
 Framework != design pattern
 Typical framework uses multiple design patterns

Application Frameworks

156
 Implements services common to a type of applications
 Programmer forms subclasses of framework classes
 Result is an application
 Inversion of control: framework controls execution flow

Applets
 Applet: Java program that runs in a web browser
 Programmer forms subclass of Applet or JApplet
 Overwrites
init/destroy
start/stop
paint

Applets

Applets
 Interacts with ambient browser
getParameter
showDocument
 HTML page contains applet tag and parameters

<applet code="BannerApplet.class" width="300" height="100">


<param name="message" value="Hello, World!"/>
<param name="fontname" value="Serif"/>
<param name="fontsize" value="64"/>

157
<param name="delay" value="10"/>
</applet>

Example Applet
 Shows scrolling banner
 init reads parameters
 start/stop start and stop timer
 paint paints the applet surface
 Ch8/applet/BannerApplet.java

Example Applet

Applets as a Framework
 Applet programmer uses inheritance
 Applet class deals with generic behavior (browser interaction)
 Inversion of control: applet calls init, start,stop,destroy

Collections Framework
 Java library supplies standard data structures
 Supplies useful services (e.g. Collections.sort, Collections.shuffle)
 Framework: Programmers can supply additional data structures, services
 New data structures automatically work with services
 New services automatically work with data structures

Collections Framework: Interface Types

158
 Collection: the most general collection interface type
 Set: an unordered collection that does not permit duplicate elements
 SortedSet: a set whose elements are visited in sorted order
 List: an ordered collection

Collections Framework: Classes


 HashSet: a set implementation that uses hashing to locate the set elements
 TreeSet: a sorted set implementation that stores the elements in a balanced
binary tree
 LinkedList and ArrayList: two implementations of the List interface type

Collections Framework

Collection Interface Type


 Collection holds elements in some way
 Different data structures have different storage strategies

boolean add(Object obj)


boolean addAll(Collection c)
void clear()
boolean contains(Object obj)
boolean containsAll(Collection c)
boolean equals(Object obj)
int hashCode()
boolean isEmpty()
Iterator iterator()
boolean remove(Object obj)
boolean removeAll(Collection c)
boolean retainAll(Collection c)
int size()
Object[] toArray()
Object[] toArray(Object[] a)

159
Iterator Interface Type
 Iterator traverses elements of collection

boolean hasNext()
Object next()
void remove()

AbstractCollection Class
 Collection is a hefty interface
 Convenient for clients, inconvenientfor implementors
 Many methods can be implemented from others (Template method!)
 Example: toArray

public Object[] toArray()


{
Object[] result = new Object[size()];
Iterator e = iterator();
for (int i=0; e.hasNext(); i++)

result[i] = e.next();
return result;
}

AbstractCollection Class
 Can't place template methods in interface
 Place them in AbstractCollection class
 AbstractCollection convenient superclass for implementors
 Only two methods undefined: size,iterator

Adding a new Class to the Framework


 Use queue from chapter 3
 Supply an iterator (with do-nothing remove method)
 add method always returns true
 Ch8/queue/Queue.java
 Ch8/queue/QueueTest.java

Adding a new Class to the Framework

160
Sets
 Set interface adds no methods to Collection!
 Conceptually, sets are a subtype of collections
 Sets don't store duplicates of the same element
 Sets are unordered
 Separate interface: an algorithm can require a Set

Lists
 Lists are ordered
 Each list position can be accessed by an integer index
 Subtype methods:

boolean add(int index, Object obj)


boolean addAll(int index, Collection c)
Object get(int index)
int indexOf(Object obj)
int lastIndexOf(Object obj)
ListIterator listIterator()
ListIterator listIterator(int index)
Object remove(int index)
Object set(int index, int Object)
List subList(int fromIndex, int toIndex)

List Iterators
 Indexing
 Bidirectional behavior
 Subtype methods:

161
int nextIndex()
int previousIndex()
boolean hasPrevious()
Object previous()
void set(Object obj)

List Classes
 ArrayList
 LinkedList
 Indexed access of linked list elements is possible, but slow
 Weakness in the design
 Partial fix in Java 1.4: RandomAccess interface

List Classes

Optional Operations
 Many operations tagged as "optional"
 Example: Collection.add, Collection.remove
 Default implementation throws exception
 Why have optional operations?

Views
 View = collection that shows objects that are stored elsewhere
 Example: Arrays.asList
 String[] strings = { "Kenya", "Thailand", "Portugal" };
List view = Arrays.asList(strings)

162
 Does not copy elements!
 Can use view for common services
otherList.addAll(view);

Views
 get/set are defined to access underlying array
 Arrays.asList view has no add/remove operations
 Can't grow/shrink underlying array
 Several kinds of views:
read-only
modifyable
resizable
...
 Optional operations avoid inflation of interfaces
 Controversial design decision

Graph Editor Framework


 Problem domain: interactive editing of diagrams
 Graph consists of nodes and edges
 Class diagram:
nodes are rectangles
edges are arrows
 Electronic circuit diagram:
nodes are transistors, resistors
edges are wires

Graph Editor Framework


 Traditional approach: programmer starts from scratch for every editor type
 Framework approach: Programmer extends graph, node, edge classes
 Framework handles UI, load/save, ...
 Our framework is kept simple
 Violet uses extension of this framework

User Interface
 Toolbar on top
 Grabber button for selecting nodes/edges
 Buttons for current node/edge type
 Menu
 Drawing area

163
User Interface

Mouse Operations
 Click on empty space: current node inserted
 Click on node or edge: select it
 Drag node when current tool an edge: connect nodes
 Drag node when current tool not an edge: move node

Division of Responsibility
 Divide code between
o framework
o specific application
 Rendering is app specific (e.g. transistor)
 Hit testing is app specific (odd node shapes)
 Framework draws toolbar
 Framework does mouse listening

Adding Nodes and Edges


 Framework draws toolbar
 How does it know what nodes/edges to draw?
 App gives a list of nodes/edges to framework at startup
 How does app specify nodes/edges?
o Class names? ("Transistor")
o Class objects? (Transistor.class)
o Node, Edge objects? (new Transistor())

164
Adding Nodes and Edges
 Objects are more flexible than classes
 new CircleNode(Color.BLACK)
new CircleNode(Color.WHITE)
 When user inserts new node, the toolbar node is cloned
Node prototype = node of currently selected toolbar button;
Node newNode = (Node) prototype.clone();
Point2D mousePoint = current mouse position;
graph.add(newNode, mousePoint);
 Example of PROTOTYPE pattern

PROTOTYPE Pattern
Context

1. A system instantiates objects of classes that are not known when the system is
built.
2. You do not want to require a separate class for each kind of object.
3. You want to avoid a separate hierarchy of classes whose responsibility it is to
create the objects.

Solution

1. Define a prototype interface type that is common to all created objects.


2. Supply a prototype object for each kind of object that the system creates.
3. Clone the prototype object whenever a new object of the given kind is required.

PROTOTYPE Pattern

PROTOTYPE Pattern

165
Name in Design Pattern Actual name (graph editor)
Prototype Node
ConcretePrototype1 CircleNode
Creator The GraphPanel that handles the mouse operation for
adding new nodes

Framework Classes
 Framework programmer implements Node/Edge interfaces
 draw draws node/edge
 getBounds returns enclosing rectangle (to compute total graph size for
scrolling)
 Edge.getStart, getEnd yield start/end nodes
 Node.getConnectionPoint computes attachment point on shape boundary
 Edge.getConnectionPoints yields start/end coordinates (for grabbers)
 clone overridden to be public

Node Connection Points

Framework Classes
 AbstractEdge class for convenience
 Programmer implements Node/Edge type or extends AbstractEdge
 Ch8/graphed/Node.java
 Ch8/graphed/Edge.java
 Ch8/graphed/AbstractEdge.java

166
Framework Classes
 Graph collects nodes and edges
 Subclasses override methods
public abstract Node[] getNodePrototypes()
public abstract Edge[] getEdgePrototypes()
 Ch8/graphed/Graph.java

Framework UI Classes
 GraphFrame: a frame that manages the toolbar, the menu bar, and the graph
panel.
 ToolBar: a panel that holds toggle buttons for the node and edge icons.
 GraphPanel: a panel that shows the graph and handles the mouse clicks and
drags for the editing commands.
 Application programmers need not subclass these classes

A Framework Instance
 Simple application
 Draw black and white nodes
 Join nodes with straight lines

Programmer responsibilities
 For each node and edge type, define a class that implements the Node or Edge
interface type
 Supply all required methods, such as drawing and containment testing.
 Define a subclass of the Graph class and supply getNodePrototypes,
getEdgePrototypes
 Supply a class with a main method

A Framework Instance

167
A Framework Instance
 Ch8/graphed/SimpleGraph.java
 Ch8/graphed/SimpleGraphEditor.java
 Ch8/graphed/CircleNode.java
 Ch8/graphed/LineEdge.java

Generic Framework Code


 Framework frees application programmer from tedious programming
 Framework can do significant work without knowing node/edge types
 Analyze two scenarios
o Add new node
o Add new edge

Add New Node


public void mousePressed(MouseEvent event)
{
Point2D mousePoint = event.getPoint();
Object tool = toolBar.getSelectedTool();
...
if (tool instanceof Node)
{
Node prototype = (Node) tool;

168
Node newNode = (Node)prototype.clone();
graph.add(newNode, mousePoint);
}
...
repaint();
}

Add New Node

Add New Edge


 First check if mouse was pressed inside existing node
public Node findNode(Point2D p)
{
for (int i = 0; i < nodes.size(); i++)
{
Node n = (Node) nodes.get(i);
if (n.contains(p)) return n;
}
return null;
}

Add New Edge


 mousePressed:
o Check if mouse point inside node
o Check if current tool is edge
o Mouse point is start of rubber band
 mouseDragged:
o Mouse point is end of rubber band; repaint
 mouseReleased:
o Add edge to graph

169
Add New Edge

Enhancing the Framework


 Edit node/edge properties
o Node colors
o Edge styles (solid/dotted)
 Framework enhancement: Edit->Properties menu pops up property dialog

Enhancing the Framework

170
Enhancing the Framework
 How to implement the dialog?
 Solved in chapter 7--bean properties!
 CircleNode exposes color property:
Color getColor()
void setColor(Color newValue)
 Property editor automatically edits color!

Using the Framework Enhancement


 Add dotted lines
 Define enumerated type LineStyle
 Two instances LineStyle.SOLID, LineStyle.DOTTED
 Add lineStyle property to LineEdge
 LineStyle has method getStroke()
 LineEdge.draw calls getStroke()
 Supply property editor for LineStyle type
 Property editor now edits line style!

Another Framework Instance


 UML Class diagram editor
 "Violet lite"

171
Another Framework Instance
 RectangularNode
 SegmentedLineEdge
 GeneralPathEdge uses general path for containment testing
 ArrowHead, BentStyle enumerate arrow and line styles
 MultiLineString property for class compartments
 ClassNode, ClassRelationshipEdge, ClassDiagramGraph
 No change to basic framework!

Edge Properties

172
Multiline String Property Editor

Enhancing the Framework II


 Violet is based on an enhancement of the book's framework
 Adds many options
o graphics export
o grid
o multiple windows

173
 Can add 3 simple graph editor classes to that framework
 App tracks framework evolution at no cost to app programmer

Enhancing the Framework II

174
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 9

Multithreading

Chapter Topics
 Thread Basics
 Thread Synchronization
 Animation

Threads
 Thread: program unit that is executed independently
 Multiple threads run simultaneously
 Virtual machine executes each thread for short time slice
 Thread scheduler activates, deactivates threads
 Illusion of threads running in parallel
 Multiprocessor computers: threads actually run in parallel

175
Running Threads
 Define class that implements Runnable
 Runnable has one method
void run()
 Place thread action into run method
 Construct object of runnable class
 Construct thread from that object
 Start thread

Running Threads
public class MyRunnable implements Runnable
{
public void run()
{
thread action
}
}
...
Runnable r = new MyRunnable();
Thread t = new Thread(t);
t.start();

Thread Example
 Run two threads in parallel
 Each thread prints 10 greetings

for (int i = 1; i <= 10; i++)


{
System.out.println(i + ": " + greeting);
Thread.sleep(100);
}

 After each printout, sleep for 100 millisec


 All threads should occasionally yield control
 sleep throws InterruptedException

Thread Example
 Ch9/greeting/GreetingProducer.java
 Ch9/greeting/ThreadTest.java

176
Thread Example
 Note: output not exactly interleaved

1: Hello, World!
1: Goodbye, World!
2: Hello, World!
2: Goodbye, World!
3: Hello, World!
3: Goodbye, World!
4: Hello, World!
4: Goodbye, World!
5: Hello, World!
5: Goodbye, World!
6: Hello, World!
6: Goodbye, World!
7: Hello, World!
7: Goodbye, World!
8: Goodbye, World!
8: Hello, World!
9: Goodbye, World!
9: Hello, World!
10: Goodbye, World!
10: Hello, World!

Starting Two Threads

177
Thread States
 Each thread has
o thread state
o priority
 Thread states:
o new (before start called)
o runnable
o blocked
o dead (after run method exits)

Thread States

178
Blocked Thread State
 Reasons for blocked state:
o Sleeping
o Waiting for I/O
o Waiting to acquire lock (later)
o Waiting for notification (later)
 Unblocks only if reason for block goes away

Scheduling Threads
 Scheduler activates new thread if
o a thread has completed its time slice
o a thread has blocked itself
o a thread with higher priority has become runnable
 Scheduler determines new thread to run
o looks only at runnable threads
o picks one with max priority

Terminating Threads
 Thread terminates when run exits
 Sometimes necessary to terminate running thread
 Don't use deprecated stop method
 Interrupt thread by calling interrupt
 Thread must cooperate and exit its run
 Thread has chance to clean up

179
Sensing Interruptions
 Thread could occasionally call
Thread.currentThread().isInterrupted()
 sleep, wait throw InterruptedException when thread interrupted
 . . . and then the interruption status is cleared!
 More robust: Catch exception and react to interruption
 Recommendation: Terminate run when sensing interruption

Sensing Interruptions
public class MyRunnable implements Runnable
{
public void run()
{
try
{
while (...)
{
do work
Thread.sleep(...);
}
}
catch (InterruptedException e) {}
clean up
}
}

Thread Synchronization
 Use bounded queue from chapter 3
 Each producer thread inserts greetings
 Each consumer thread removes greetings
 Two producers, one consumer

Producer Thread
int i = 1;
while (i <= repetitions)
{
if (!queue.isFull())
{
queue.add(i + ": " + greeting); i++;
}
Thread.sleep((int)(Math.random() * DELAY));
}

Consumer Thread

180
int i = 1;
while (i <= repetitions)
{
if (!queue.isEmpty())
{
Object greeting = queue.removeFirst();
System.out.println(greeting);
i++;
}
Thread.sleep((int)(Math.random() * DELAY));
}

Expected Program Output


1: Hello, World!
1: Goodbye, World!
2: Hello, World!
3: Hello, World!
...
99: Goodbye, World!
100: Goodbye, World!

Why is Output Corrupted?


 Sometimes program gets stuck and doesn't complete
 Can see problem better when turning debugging on
queue.setDebug(true);

 Ch9/queue1/ThreadTest.java
 Ch9/queue1/Producer.java
 Ch9/queue1/Consumer.java
 Ch9/queue1/Queue.java

Race Condition Scenario


 First thread calls add and executes
elements[tail] = anObject;
 First thread at end of time slice
 Second thread calls add and executes
elements[tail] = anObject;
tail++;
 Second thread at end of time slice
 First thread executes
tail++;

Race Condition Scenario

181
Object Locks
 Each object has a lock
 Thread can lock, unlock object
 No other thread can lock object until unlocked
 Use synchronized method
 Calling synchronized method locks implicit parameter
 No other thread can call another synchronized method on same object
 Place thread-sensitive code inside synchronized methods
public synchronized void add(Object anObject) { ... }

182
Scenario with Synchronized Methods
 First thread calls add and executes
elements[tail] = anObject;
 First thread at end of time slice
 Second thread tries to call add, blocks
 First thread executes
tail++;
 First thread completes add, unlocks queue
 Second thread unblocked
 Second thread calls add

Visualizing Locks
 Object = phone booth
 Thread = person
 Locked object = closed booth
 Blocked thread = person waiting for booth to open

Visualizing Locks

183
Deadlocks
 Not enough to synchronize add,removeFirst
 if (!queue.isFull()) queue.add(...);
can still be interrupted
 Must move test inside add method
 What should add do if queue is full?

Deadlocks
 Consumer will remove objects
 Producer needs to wait
 Producer can't go to sleep inside locked object
 Person sleeping in phone booth, waiting for technician?

Avoiding Deadlocks
 Call wait in add method:
public synchronized void add(Object anObject)
throws InterruptedException
{
while (isFull())
wait();
}
 Waiting thread is blocked
 Waiting thread is added to wait set of object

Avoiding Deadlocks
 To unblock waiting thread, some other thread calls notifyAll
 Must be called on same object
 Call when state changes
public synchronized Object removeFirst()
{
...
notifyAll();
}
 All waiting threads removed from wait set, unblocked
 Ch9/queue2/Queue.java

Algorithm Animation
 Use thread to make progress in algorithm
 Display algorithm state

184
 Example: Animate Ch9/animation/MergeSorter.java
 Pause inside compare method
 Pass custom comparator
Comparator comp = new
Comparator()
{
public void compare(Object o1, Object o2)
{
draw current state
pause thread
return comparison result
}
};

Algorithm Animation

Algorithm Animation
 Ch9/animation1/Sorter.java
 Ch9/animation1/ArrayPanel.java
 Ch9/animation1/AnimationTest.java

Pausing and Running the Animation


 Want to pause animation until button is clicked
 Need to coordinate UI thread, animation thread
 Easier to understand coordination with custom object
 Both threads query, manipulate gate

185
Gate
 Works like a security gate
 Sorter thread = car approaching gate
 Passes through if gate open, pauses otherwise
 Animation thread = security guard
 Step button opens gate to let one car through
 Run button deactivates gate--alway open

Gate

Pausing and Running the Animation


 compare method checks gate
if (gate.isActive())
gate.waitForOpen();
 Button callbacks set gate state
 Ch9/animation2/Gate.java
 Ch9/animation2/AnimationTest.java

Animation Classes

186
187
Object-Oriented Design & Patterns
Cay S. Horstmann

Chapter 10

More Design Patterns

Chapter Topics
 The ADAPTER Pattern
 Actions and the COMMAND Pattern
 The FACTORY METHOD Pattern
 The PROXY Pattern
 The SINGLETON Pattern
 The VISITOR Pattern
 Other Design Patterns

Adapters
 Cable adapter: adapts plug to foreign wall outlet
 OO Programming; Want to adapt class to foreign interface type
 Example: Add CarIcon to container
 Problem: Containers take components, not icons

188
 Solution: Create an adapter that adapts Icon to Component
 Ch10/adapter/IconAdapter.java
 Ch10/adapter/IconAdapterTest.java

The ADAPTER Pattern


Context

1. You want to use an existing class (adaptee) without modifying it.


2. The context in which you want to use the class requires target interface that is
different from that of the adaptee.
3. The target interface and the adaptee interface are conceptually related.

The ADAPTER Pattern


Solution

1. Define an adapter class that implements the target interface.


2. The adapter class holds a reference to the adaptee. It translates target methods to
adaptee methods.
3. The client wraps the adaptee into an adapter class object.

The ADAPTER Pattern

The ADAPTER Pattern

189
Name in Design Actual Name (Icon->Component)
Pattern
Adaptee Icon
Target JComponent
Adapter IconAdapter
Client The class that wants to add icons into a container
targetMethod() paintComponent(), getPreferredSize()
adapteeMethod() paintIcon(), getIconWidth(),
getIconHeight()

The ADAPTER Pattern


 In stream library
 Input streams read bytes
 Readers read characters
 Non-ASCII encoding: multiple bytes per char
 System.in is a stream
 What if you want to read characters?
 Adapt stream to reader
 InputStreamReader

The ADAPTER Pattern


Name in Design Pattern Actual Name (Stream->Reader)
Adaptee InputStream
Target Reader
Adapter InputStreamReader
Client The class that wants to read text from an input stream
targetMethod() read (reading a character)
adapteeMethod() read (reading a byte)

User Interface Actions


 Multiple routes to the same action
 Example: Cut a block of text
o Select Edit->Cut from menu
o Click toolbar button
o Hit Ctrl+X
 Action can be disabled (if nothing is selected)

190
 Action has state
 Action should be an object

User Interface Actions

The Action Interface Type


 Extends ActionListener
 Can be enabled/disabled
 Additional state, including
o Action name
o Icon
 helloAction.putValue(Action.NAME, "Hello");
 menu.add(helloAction);
 Extend AbstractAction convenience class

The Action Interface Type

191
Action Example
 Ch10/command/CommandTest.java
 Ch10/command/GreetingAction.java

The COMMAND Pattern


Context

1. You want to implement commands that behave like objects


o because you need to store additional information with commands
o because you want to collect commands.

The COMMAND Pattern


Solution

1. Define a command interface type with a method to execute the command.


2. Supply methods in the command interface type to manipulate the state of
command objects.
3. Each concrete command class implements the command interface type.
4. To invoke the command, call the execute method.

192
The COMMAND Pattern

The COMMAND Pattern


Name in Design Pattern Actual Name (Swing actions)
Command Action
ConcreteCommand subclass of AbstractAction
execute() actionPerformed()
state name and icon

Factory Methods
 Every collection can produce an iterator
Iterator iter = list.iterator()
 Why not use constructors?
Iterator iter = new LinkedListIterator(list);
 Drawback: not generic
Collection coll = ...;
Iterator iter = new ???(coll);
 Factory method works for all collections
Iterator iter = coll.iterator();
 Polymorphism!

The FACTORY METHOD Pattern


Context

193
1. A type (the creator) creates objects of another type (the product).
2. Subclasses of the creator type need to create different kinds of product objects.
3. Clients do not need to know the exact type of product objects.

The FACTORY METHOD Pattern


Solution

1. Define a creator type that expresses the commonality of all creators.


2. Define a product type that expresses the commonality of all products.
3. Define a method, called the factory method, in the creator type.
The factory method yields a product object.
4. Each concrete creator class implements the factory method so that it returns an
object of a concrete product class.

The FACTORY METHOD Pattern

The FACTORY METHOD Pattern


Name in Design Pattern Actual Name (iterator)
Creator Collection
ConcreteCreator A subclass of Collection
factoryMethod() iterator()
Product Iterator
ConcreteProduct A subclass of Iterator (which is often anonymous)

194
Not a FACTORY METHOD
 Not all "factory-like" methods are instances of this pattern
 Create DateFormat instances
DateFormat formatter = DateFormat.getDateInstance();
Date now = new Date();
String formattedDate = formatter.format(now);
 getDateInstance is a static method
 No polymorphic creation

Proxies
 Proxy: a person who is authorized to act on another person s behalf
 Example: Delay instantiation of object
 Expensive to load image
 Not necessary to load image that user doesn't look at
 Proxy defers loading until user clicks on tab

Deferred Image Loading

Deferred Image Loading


 Normally, programmer uses image for label:
JLabel label = new JLabel(new ImageIcon(imageName));
 Use proxy instead:
JLabel label = new JLabel(new ImageProxy(imageName));

195
 paintIcon loads image if not previously loaded
public void paintIcon(Component c, Graphics g, int x,
int y)
{
if (image == null) image = new ImageIcon(name);
image.paintIcon(c, g, x, y);
}

Proxies
 Ch10/proxy/ImageProxy.java
 Ch10/proxy/ProxyTest.java
 "Every problem in computer science can be solved by an additional level of
indirection"
 Another use for proxies: remote method invocation

The PROXY Pattern


Context

1. A class (the real subject) provides a service that is specified by an interface type
(the subject type)
2. There is a need to modify the service in order to make it more versatile.
3. Neither the client nor the real subject should be affected by the modification.

The PROXY Pattern


Solution

1. Define a proxy class that implements the subject interface type.


The proxy holds a reference to the real subject, or otherwise knows how to locate
it.
2. The client uses a proxy object.
3. Each proxy method invokes the same method on the real subject and provides the
necessary modifications.

The PROXY Pattern

196
The PROXY Pattern
Name in Design Pattern Actual Name (image proxy)
Subject Icon
RealSubject ImageIcon
Proxy ImageProxy
request() The methods of the Icon interface type
Client JLabel

Singletons
 "Random" number generator generates predictable stream of numbers
 Example: seed = (seed * 25214903917 + 11) % 248
 Convenient for debugging: can reproduce number sequence
 Only if all clients use the same random number generator
 Singleton class = class with one instance

Random Number Generator Singleton


public class SingleRandom
{
private SingleRandom() { generator = new Random(); }
public void setSeed(int seed) { generator.setSeed(seed);
}
public int nextInt() { return generator.nextInt(); }

197
public static SingleRandom getInstance() { return
instance; }
private Random generator;
private static SingleRandom instance = new
SingleRandom();
}

The SINGLETON Pattern


Context

1. All clients need to access a single shared instance of a class.


2. You want to ensure that no additional instances can be created accidentally.

The SINGLETON Pattern


Solution

1. Define a class with a private constructor.


2. The class constructs a single instance of itself.
3. Supply a static method that returns a reference to the single instance.

Not a SINGLETON
 Toolkit used for determining screen size, other window system parameters
 Toolkit class returns default toolkit
Toolkit kit = Toolkit.getDefaultToolkit();
 Not a singleton--can get other instances of Toolkit
 Math class not example of singleton pattern
 No objects of class Math are created

Inflexible Hierarchies
 How can one add operations to compound hierarchies?
 Example: AWT Component, Container, etc. form hierarchy
 Lots of operations: getPreferredSize,repaint
 Can't add new methods without modifying Component class
 VISITOR pattern solves this problem
 Each class must support one method
void accept(Visitor v)

Inflexible Hierarchies

198
Visitors
 Visitor is an interface type
 Supply a separate class for each new operation
 Most basic form of accept method:
public void accept(Visitor v) { v.visit(this); }
 Programmer must implement visit

Visitors
 Problem: Operation may be different for different element types
 Can't rely on polymorphism
 Polymorphism assumes fixed set of methods, defined in superclass
 Trick: Can use variable set of methods if set of classes is fixed
 Supply separate visitor methods:
public interface Visitor
{
void visitElementType1(ElementType1 element);
void visitElementType2(ElementType2 element);
...
void visitElementTypen(ElementTypen element);
}

Visitors
 Example: Directory tree
 Two kinds of elements: DirectoryNode,FileNode
 Two methods in visitor interface type:
void visitDirectoryNode(DirectoryNode node)
void visitFileNode(FileNode node)

199
Double Dispatch
 Each element type provides methods:
public class ElementTypei
{
public void accept(Visitor v) {
v.visitElementTypei(this); }
...
}
 Completely mechanical
 Example:
public class DirectoryNode
{
public void accept(Visitor v) {
v.visitDirectoryNode(this); }
...
}

Visitor Example
 Standard File class denotes both files and directories
 Improved design: FileNode,DirectoryNode
 Common interface type: FileSystemNode
 Accepts FileSystemVisitor
 Visitor methods:
visitFileNode
visitDirectoryNode

Visitor Example

200
Visitor Example
 Actual visitor: PrintVisitor
 Prints names of files (in visitFileNode)
 Lists contents of directories (in visitDirectoryNode)
 Maintains indentation level
..
command
CommandTest.java
GreetingAction.java
visitor
FileNode.java
DirectoryNode.java

Visitor Example
 ch10/visitor/FileSystemNode.java
 ch10/visitor/FileNode.java
 ch10/visitor/DirectoryNode.java
 ch10/visitor/FileSystemVisitor.java
 ch10/visitor/PrintVisitor.java
 ch10/visitor/VisitorTest.java

201
Double Dispatch Example
 DirectoryNode node = new DirectoryNode(new
File(".."));
node.accept(new PrintVisitor());
 node is a DirectoryNode
 Polymorphism: node.accept calls DirectoryNode.accept
 That method calls v.visitDirectoryNode
 v is a PrintVisitor
 Polymorphism: calls PrintVisitor.visitDirectoryNode
 Two polymorphic calls determine
o node type
o visitor type

Double Dispatch Example

The VISITOR Pattern


Context

1. An object structure contains element classes of multiple types, and you want to
carry out operations that depend on the object types.
2. The set of operations should be extensible over time.
3. The set of element classes is fixed.

The VISITOR Pattern


Solution

202
1. Define a visitor interface type that has methods for visiting elements of each of
the given types.
2. Each element class defines an accept method that invokes the matching element
visitation method on the visitor parameter.
3. To implement an operation, define a class that implements the visitor interface
type and supplies the operation s action for each element type.

The VISITOR Pattern

The VISITOR Pattern


Name in Design Pattern Actual Name (file system visitor)
Element FileSystemNode
ConcreteElement FileNode, DirectoryNode
Visitor FileSystemVisitor
ConcreteVisitor PrintVisitor

Other Design Patterns


 Abstract Factory

203
 Bridge
 Builder
 Chain of Responsibility
 Flyweight
 Interpreter
 Mediator
 Memento
 State

Conclusion: What You Learned


1. Object-oriented design
The design methodology
CRC cards and UML diagrams
Design patterns
2. Advanced Java
Interface types, polymorphism, and inheritance
Inner classes
Reflection
Multithreading
Collections
3. User interface programming
Building Swing applications
Event handling
Graphics programming

204

You might also like