SlideShare a Scribd company logo
1 of 4
Download to read offline
44 Java™
Report | OCTOBER 2001 http://www.javareport.com
T
HE CONTROL-FLOW structures of Java have
remained fairly stable since their arrival in C three
decades ago. They express the core structured-
programming primitives of sequential, selective, and
repetitive execution, as well as discontinuous control
flow, such as breaking from a loop. Selective execution
is much as it used to be, except it has lost some ground
to the use of polymorphism. The basic refinement to
sequential execution has been its disruption through
exceptions and its multiplication through threading,
both of which are supported in the heart of the language.
My previous two columns1, 2 explored patterns that cap-
tured differences in practice between single-threaded
and multi-threaded programming, and exception-free
and exception-throwing code.
Iteration constructs have changed little since days of
yore, but the subject of iteration has been objectified and
pattern-enriched with collections and iterators. To begin
at the beginning, there are five features that define any
iteration:
• The initialization to start the loop.
• The continuation condition to keep it running (or termi-
nation condition to stop it, depending on whether you
regard the glass as half-full or half-empty).
• The body of the loop to do the work.
• The advancement of the iteration to go around again.
This may be a distinct action, i.e., an increment, or a side
effect of something in the body of the loop.
• The finalization to clean up after the loop. This feature is
often optional, a no-op.
It is no coincidence that the four mandatory parts of a
loop correspond to the anatomy of the for.
The ITERATOR pattern3 represents what many OO devel-
opers think of as the design for iteration in an object sys-
tem, but there is more to iteration abstraction than just
ITERATOR. The rest of this column looks at three iteration
patterns whose solutions differ in their response to thread-
ing, distribution, exceptions, and parameterization. So
let’s start by looking in detail at something that should be
fairly familiar.
Iteration Pattern 1: ITERATOR
Support iteration over an encapsulated collection by plac-
ing responsibility for iteration into a separate object.
Problem. How can elements
of a collection be accessed
conveniently, sequentially, and
efficiently without exposing
its underlying representation
or making it less cohesive?
If the representation of a
collection is accessible, users
can access the internal struc-
ture of the object directly so
they can iterate over it.
However, users can under-
mine its structure, intention-
ally or otherwise, giving rise
to subtle bugs or assumptions
about undocumented class
behavior. Their code is also strongly coupled to the imple-
mentation details of the collection, so any changes to the
data structure will inevitably break the client code, and
any change of collection type will inevitably cause a
rewrite. It is not possible to work reasonably through an
interface if the implementation of a collection must be
known in order to use it.
It is tempting to use a conventional integer index to
look up elements. However, this is an abstraction too far,
hiding potentially expensive operations behind an inno-
cent-looking interface. To loop over every element in an
array-based sequence with an index is a linear-time oper-
ation (O(N) in O-notation), with the generated code visit-
ing each element precisely once in constant time. To do
the same for a linked-list implementation is significantly
more expensive (a pricey O(N2)) as previously visited
links in the list are retraversed each time to find the next
indexed element. To get a feel for what this means in
practice, an array of 10 elements will require 10 accesses,
whereas a list of 10 will require 55 link traversals. But
where an array of 100,000 elements requires 100,000
accesses, a list of the same length requires more than 5
billion link traversals. Hiding such a profound difference
between a random-access structure and a sequential-
access structure behind a weakly specified get interface
(no non-functional guarantees or warnings are given) is
questionable design.
In sequential-access cases, it can be more effective to
make use of a toArray method to get a snapshot of all the
elements and iterate over the returned array instead.
However, this still requires the user to know the imple-
Kevlin Henney is an independent consultant and trainer based in
the UK.
Kevlin Henney/kevlin@curbralan.com
Patterns In Java
Iteration constructs
have changed little
since days of yore,
but the subject of
iteration has been
objectified and
pattern-enriched
with collections
and iterators.
A tale of three patterns
http://www.javareport.com OCTOBER 2001 | Java™
Report 45
mentation type of the collection, and it is not without its
own overhead.
Iteration can be supported directly in the collection
by providing the collection with the notion of a current
position. Unfortunately, this restricts a collection to only
a single iteration at a time. The methods of the collection
cannot use the iteration mechanism for fear they may
upset an existing iteration; a collection may be refer-
enced by many objects, each with its own use for the
notion of a “current position,” and there is therefore a
strong possibility of interference between them. There is
also a question of cohesion—or rather the lack of it—
when a collection’s interface and implementation are
asked to represent both a collection of items and a cur-
rently selected item.
Solution. Place responsibility for iteration into an object
separate from the object being iterated over. The funda-
mental features of iteration must be supported, with the
most common division of features being for the collection
to support creation and initialization of an iterator object,
often using a FACTORY METHOD,3 and the iterator object
itself supporting the traversal features, either as sepa-
rate methods or as combined methods—COMMAND-QUERY
SEPARATION vs. COMBINED METHOD.1
From the standard java.util package, the Iterator and
Collection interface offer an example of the ITERATOR pattern
in action:
public interface Iterator
{
boolean hasNext();
Object next(); // Combined Method for advance and retrieve
...
}
public interface Collection
{
...
Iterator iterator(); // Factory Method
...
}
The underlying collection data structure is now fully
hidden, but without hiding complexity costs from the
user. There may be some additional overhead as a result
of creating an additional object and adding a managed
level of indirection. Whether this is significant depends
on the task the iteration is being carried out for and the
nature of the application.
The user is now freed from any dependency on imple-
mentation details—to the extent that a collection class may
be modified without affecting the code, or an alternative
collection type may be substituted, assuming an interface-
based approach is taken. It is even possible for the collec-
tion to be virtual in the sense there is no real collection of
objects at all, i.e., objects on an input stream or objects that
are calculated on the fly.
There is coupling between the iterator and the collec-
tion classes, suggesting the iterator class should be nested
within the collection class definition. It may be as a public
class in its own right or, more likely, a private inner or stat-
ic class implementing an interface such as java.util.Iterator.
If the iterator is simple, it may be reasonable to define it as
an anonymous inner class within the body of the actual
creation method.
Multiple traversals can now be supported, but the ques-
tion of validity arises if the collection is modified while the
iteration is carried out. The decision has to be taken as to
whether invalidating iterators is reasonable or not for a
given design, and then what to do about it.
• For small collections an iterator can take a snapshot of
the collection’s contents, i.e., such as using toArray and
iterate over that. This has the disadvantage of a costly
initialization, but the advantage of guaranteeing itera-
tion validity and content, even with multiple threads.
• Another approach to managing iterator validity is to
establish an OBSERVER relationship3 between the itera-
tor and the collection, so that the iterator is notified of
any changes in the collection, i.e., either invalidating
itself or advancing itself an element if its current ele-
ment is removed.
• A version stamp can also be used, so the collection has
a counter that is only modified when the collection
structure is modified. An iterator remembers the ver-
sion of its creation and always checks to see that the
target collection has not changed. This approach is
used in the Java Collections API, but has the disadvan-
tage that any change—even one that would not invali-
date the current iterator—will cause an exception to be
thrown.
• A more tolerant and laissez-faire approach is to only
throw an exception when the iterator absolutely can-
not perform an operation due to changes. For instance,
increasing the size of an array-based collection need
not invalidate iterators, but reducing the size below
the index of the current iterator would. Removing ele-
ments is generally safe from a linked list, and can also
be made safe if the current element is removed—either
the outgoing references continue to refer to adjacent
links to allow iteration to continue, or the outgoing
references are nulled, leading to an exception on the
next advance.
• The move to the next element, the extraction of the ele-
ment, and the check that it is actually there can all be
combined into a single method. This use of COMBINED
METHOD1 ensures that the traversal aspects of the loop
are uninterruptible and can be synchronized by the iter-
ator rather than the user of the iterator. This technique
can be combined with any of the strategies above. Note
that although java.util.Iterator has a COMBINED METHOD, it
does not fulfill the role just described.
The separation of iteration from the interface of the
collection means that collection users can customize
their own iteration by adapting the raw iterator, i.e.,
defining a search iterator that skips elements that do not
Patterns In Java
match some particular condition when it traverses.
Iteration Pattern 2: ENUMERATION METHOD
Support encapsulated iteration over a collection by placing
responsibility for iteration into a method on the collection.
Problem. Some collection types have representations
that do not conveniently support ITERATOR-based travers-
al. How can elements of such a collection be sequentially
and efficiently accessed without complicating and com-
promising the implementation of the collection?
For instance, a dictionary implemented as a sorted bina-
ry tree can be implemented minimally with each tree node
having a link to the child node on the left and on the right,
plus the actual data element, and so on recursively down
the subtrees. The subtree on the left has values that com-
pare lower than the data element, while those in the sub-
tree on the right compare higher:
public class SortedBinaryTree
{
...
private static class Node
{
String key, value;
Node left, right;
}
private Node root;
}
The simplest approach for visiting each element in
order is to recurse through the subtree on the left before
dealing with the key and value in the current node, and
then recurse through the subtree on the right. However,
this data structure will not easily support an iterator. The
traversal is broken up, and the context for recursion is
lost. One way to allow the iterator to retain context is to
add a parent link so the iterator can navigate both up and
down a tree:
public class SortedBinaryTree
{
...
private static class Node
{
String key, value;
Node left, right, up;
}
private Node root;
}
However, this complicates the management of the tree
and adds a small overhead—sometimes insignificant—to
each node. An alternative ITERATOR implementation does
not require a parent link, and captures the depth context
itself in a Stack:
public class SortedBinaryTree
{
public class static Iterator implements java.util.Iterator
{
...
private java.util.Stack nodes; // nodes to revisit
}
...
}
The stack places the complexity in the iterator rather
than the collection, but can be fragile if the collection’s
structure changes during iteration.
In each case, there are further issues if something like
the standard Iterator interface is used for a dictionary. It
provides only for returning a single value, and so a com-
bined data structure to represent the key-value pair must
be used. Note that this problem does not arise if COMMAND-
QUERY SEPARATION is used.
More generally, there are times when a collection
requires some pre- and post-iteration code to be executed
before and after the traversal. The most obvious and com-
mon case is synchronization against threaded interruption.
Leaving users to do it for themselves is tedious and error
prone and, specifically referring to thread synchronization,
a synchronized block is problematic because it can give the
illusion of safety without any of the safety.1
Solution. Bring the iteration inside the collection and
encapsulate it in a single method responsible for complete
traversal. The task of the loop—what would normally be
its body—is passed in as a COMMAND object3 and is applied
to each element in turn (see Listing 1).
The method applies any of the relevant pre- and post-
iteration actions itself, performing the loop in between,
effectively atomically. Different loop strategies can be sup-
ported easily by adding new methods, rather than requir-
ing a whole new object type, i.e., for pre-order traversal.
This is particularly useful for recursive data structures,
such as COMPOSITE objects.3
The ENUMERATION METHOD4 is a fundamental iteration
pattern that encapsulates the actual control flow of the
traversal loop. There are strong similarities with the
TEMPLATE METHOD design pattern,3 as well as VISITOR3 and
EXECUTE-AROUND METHOD.2 ENUMERATION METHOD can be
considered an inversion of the ITERATOR model, both in
terms of its flow of control and responsibilities. The per-
formance of an ENUMERATION METHOD is directly compara-
ble to that of an ITERATOR.
Iteration Pattern 3: BATCH METHOD
Group multiple collection accesses together to reduce the
cost of multiple individual accesses.
Problem. How can many actions be treated atomically?
In particular, how can multiple operations and accesses on
a collection be handled efficiently and without interrup-
tion? In a distributed system—or any other environment
involving access latency, such as database access—iterated
simple operations use up bandwidth:
Patterns In Java
46 Java™
Report | OCTOBER 2001 http://www.javareport.com
http://www.javareport.com OCTOBER 2001 | Java™
Report 47
for(each key of interest)
{
...
dictionary.put(key, value);
}
for(each key of interest)
{
value = dictionary.get(key);
...
}
While ITERATOR allows traversal of a sequence in an
abstract and controlled fashion, it does not itself address
concurrency and efficiency issues. A COMBINED METHOD
addresses the basic concurrency issues, and can fold three
operations into one; however, this only reduces the num-
ber of accesses, not the number of times a cost-incurring
loop is performed.
Solution. Define a single method that performs the
action repeatedly. The method is declared to take all the
arguments for each execution of the action, i.e., an array or
collection, and to return results by similar means. This
single method folds the repetition into a data structure
rather than a loop, so that looping is performed before or
after the method call, in preparation or in follow up.
Therefore, the cost of access is reduced to a single access,
or a few “chunked” accesses:
interface RemoteDictionary ...
{
Object[] get(Object[] keys);
void put(Object[] keys, Object[] values);
...
}
Each method access is now more expensive, but the
overall cost has been reduced. Such accesses can also be
synchronized as appropriate within the method call. The
trade-off in complexity is that significantly more house-
keeping is performed to set up and work with the results
of the call, and more intermediate data structures are
required. The BATCH METHOD pattern is found in many
distributed system architectures, such as the CORBA
Common Object Services.5 It can be considered as taking
the COMBINED METHOD pattern to its logical extreme in com-
bining many iterations into a single shot.
Conclusion
What drives pattern-based design is not that patterns
embody neat fragments of design—although this is often
true—but that any given pattern can be considered in ten-
sion with one or more other patterns. These other pat-
terns compete as design alternatives, with the trade-offs
in their forces and consequences making all the differ-
ence, pulling the design one way and another. Sometimes
there is a clear winner and the consideration of alterna-
tives does not add anything except time spent mulling
over the detail at the water cooler, on the whiteboard, or
on the way home. However, at other times having a
default case you always apply, without question, can
have quite the opposite effect, accidentally brushing sig-
nificant concerns under the carpet. It is here that having
patterns presented together and in opposition captures
more of the spirit of the design, even in something as
humble and everyday as iteration. s
References
1. Henney, K. “A Tale of Two Patterns,” Java Report,
Vol. 5, No. 12, December 2000, available at http://www.
curbralan.com.
2. Henney, K. “Another Tale of Two Patterns,” Java Report,
Vol. 6, No. 3, March 2001, available at http://www.
curbralan.com.
3. Gamma, E., et al. Design Patterns: Elements of Reusable
Object-Oriented Software, Addison-Wesley, 1995.
4. Beck, K. Smalltalk Best Practice Patterns, Prentice Hall,
1997.
5. Object Management Group (OMG). CORBAservices:
The Common Object Services Specification, available at
http://www.omg.org.
Patterns In Java
Iteration over a sorted binary tree using recursive descent in
an enumeration method
public interface KeyValueTask
{
void apply(String key, String value);
}
public class SortedBinaryTree
{
public synchronized void forEachDo(KeyValueTask toDo)
{
forEachDo(toDo, root);
}
private void forEachDo(KeyValueTask toDo, Node node)
{
if(node != null)
{
forEachDo(toDo, node.left);
toDo.apply(node.key, node.value);
forEachDo(toDo, node.right);
}
}
...
}
tree.forEachDo(new KeyValueTask() {
public void apply(String key, String value)
{ System.out.println(key + “ -> “ + value); }
});
LISTING 1

More Related Content

What's hot

Introduction to design_patterns
Introduction to design_patternsIntroduction to design_patterns
Introduction to design_patternsamitarcade
 
Oracle plsql and d2 k interview questions
Oracle plsql and d2 k interview questionsOracle plsql and d2 k interview questions
Oracle plsql and d2 k interview questionsArunkumar Gurav
 
Oracle plsql and d2 k interview question1
Oracle plsql and d2 k interview question1Oracle plsql and d2 k interview question1
Oracle plsql and d2 k interview question1Arunkumar Gurav
 
Introducing generic types
Introducing generic typesIntroducing generic types
Introducing generic typesIvelin Yanev
 
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...Raffi Khatchadourian
 
Poster on Automated Refactoring of Legacy Java Software to Default Methods
Poster on Automated Refactoring of Legacy Java Software to Default MethodsPoster on Automated Refactoring of Legacy Java Software to Default Methods
Poster on Automated Refactoring of Legacy Java Software to Default MethodsRaffi Khatchadourian
 

What's hot (7)

Introduction to design_patterns
Introduction to design_patternsIntroduction to design_patterns
Introduction to design_patterns
 
Oracle plsql and d2 k interview questions
Oracle plsql and d2 k interview questionsOracle plsql and d2 k interview questions
Oracle plsql and d2 k interview questions
 
Oracle plsql and d2 k interview question1
Oracle plsql and d2 k interview question1Oracle plsql and d2 k interview question1
Oracle plsql and d2 k interview question1
 
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
Towards Improving Interface Modularity in Legacy Java Software Through Automa...Towards Improving Interface Modularity in Legacy Java Software Through Automa...
Towards Improving Interface Modularity in Legacy Java Software Through Automa...
 
Introducing generic types
Introducing generic typesIntroducing generic types
Introducing generic types
 
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
Automated Refactoring of Legacy Java Software to Default Methods Talk at ICSE...
 
Poster on Automated Refactoring of Legacy Java Software to Default Methods
Poster on Automated Refactoring of Legacy Java Software to Default MethodsPoster on Automated Refactoring of Legacy Java Software to Default Methods
Poster on Automated Refactoring of Legacy Java Software to Default Methods
 

Viewers also liked

Creating Stable Assignments
Creating Stable AssignmentsCreating Stable Assignments
Creating Stable AssignmentsKevlin Henney
 
Introducing the FLUID Principles
Introducing the FLUID PrinciplesIntroducing the FLUID Principles
Introducing the FLUID PrinciplesKevlin Henney
 
The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...Alberta Soranzo
 
97 Things Every Programmer Should Know
97 Things Every Programmer Should Know97 Things Every Programmer Should Know
97 Things Every Programmer Should KnowKevlin Henney
 
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015Codemotion
 
A Tale of Two Patterns
A Tale of Two PatternsA Tale of Two Patterns
A Tale of Two PatternsKevlin Henney
 
DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)dpc
 
Seven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java ProgrammersSeven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java ProgrammersKevlin Henney
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseKevlin Henney
 
SOLID Deconstruction
SOLID DeconstructionSOLID Deconstruction
SOLID DeconstructionKevlin Henney
 
Collections for States
Collections for StatesCollections for States
Collections for StatesKevlin Henney
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our WaysKevlin Henney
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseKevlin Henney
 

Viewers also liked (18)

Creating Stable Assignments
Creating Stable AssignmentsCreating Stable Assignments
Creating Stable Assignments
 
Introducing the FLUID Principles
Introducing the FLUID PrinciplesIntroducing the FLUID Principles
Introducing the FLUID Principles
 
The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...
 
97 Things Every Programmer Should Know
97 Things Every Programmer Should Know97 Things Every Programmer Should Know
97 Things Every Programmer Should Know
 
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
 
A Tale of Two Patterns
A Tale of Two PatternsA Tale of Two Patterns
A Tale of Two Patterns
 
DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)
 
Seven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java ProgrammersSeven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java Programmers
 
Patterns of Value
Patterns of ValuePatterns of Value
Patterns of Value
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
 
SOLID Deconstruction
SOLID DeconstructionSOLID Deconstruction
SOLID Deconstruction
 
Collections for States
Collections for StatesCollections for States
Collections for States
 
Substitutability
SubstitutabilitySubstitutability
Substitutability
 
Framing the Problem
Framing the ProblemFraming the Problem
Framing the Problem
 
Driven to Tests
Driven to TestsDriven to Tests
Driven to Tests
 
Immutability FTW!
Immutability FTW!Immutability FTW!
Immutability FTW!
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
 

Similar to A Tale of Three Patterns

‘go-to’ general-purpose sequential collections - from Java To Scala
‘go-to’ general-purpose sequential collections -from Java To Scala‘go-to’ general-purpose sequential collections -from Java To Scala
‘go-to’ general-purpose sequential collections - from Java To ScalaPhilip Schwarz
 
24 collections framework interview questions
24 collections framework interview questions24 collections framework interview questions
24 collections framework interview questionsArun Vasanth
 
Conventional and Reasonable
Conventional and ReasonableConventional and Reasonable
Conventional and ReasonableKevlin Henney
 
Something for Nothing
Something for NothingSomething for Nothing
Something for NothingKevlin Henney
 
Java interview questions
Java interview questionsJava interview questions
Java interview questionsamit kumar
 
Top 371 java fa qs useful for freshers and experienced
Top 371 java fa qs useful for freshers and experiencedTop 371 java fa qs useful for freshers and experienced
Top 371 java fa qs useful for freshers and experiencedGaurav Maheshwari
 
Java Faqs useful for freshers and experienced
Java Faqs useful for freshers and experiencedJava Faqs useful for freshers and experienced
Java Faqs useful for freshers and experiencedyearninginjava
 
1. Java Collections Framework Introduction
1. Java Collections Framework Introduction1. Java Collections Framework Introduction
1. Java Collections Framework IntroductionBharat Savani
 
The 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryThe 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryguestebd714
 
The 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryThe 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryachraf_ing
 
Slide Dasar Materi Java Collection Framework
Slide Dasar Materi Java Collection FrameworkSlide Dasar Materi Java Collection Framework
Slide Dasar Materi Java Collection FrameworkBayu Rimba
 
Review oop and ood
Review oop and oodReview oop and ood
Review oop and oodthan sare
 
Learn advanced java programming
Learn advanced java programmingLearn advanced java programming
Learn advanced java programmingTOPS Technologies
 
Design Pattern Notes: Nagpur University
Design Pattern Notes: Nagpur UniversityDesign Pattern Notes: Nagpur University
Design Pattern Notes: Nagpur UniversityShubham Narkhede
 
All 23 Design patterns in one page front and back
All 23 Design patterns in one page front and backAll 23 Design patterns in one page front and back
All 23 Design patterns in one page front and backTrey Brister
 

Similar to A Tale of Three Patterns (20)

‘go-to’ general-purpose sequential collections - from Java To Scala
‘go-to’ general-purpose sequential collections -from Java To Scala‘go-to’ general-purpose sequential collections -from Java To Scala
‘go-to’ general-purpose sequential collections - from Java To Scala
 
24 collections framework interview questions
24 collections framework interview questions24 collections framework interview questions
24 collections framework interview questions
 
Java mcq
Java mcqJava mcq
Java mcq
 
Java interview questions
Java interview questionsJava interview questions
Java interview questions
 
Conventional and Reasonable
Conventional and ReasonableConventional and Reasonable
Conventional and Reasonable
 
Something for Nothing
Something for NothingSomething for Nothing
Something for Nothing
 
Java interview questions
Java interview questionsJava interview questions
Java interview questions
 
Top 371 java fa qs useful for freshers and experienced
Top 371 java fa qs useful for freshers and experiencedTop 371 java fa qs useful for freshers and experienced
Top 371 java fa qs useful for freshers and experienced
 
Java Faqs useful for freshers and experienced
Java Faqs useful for freshers and experiencedJava Faqs useful for freshers and experienced
Java Faqs useful for freshers and experienced
 
1. Java Collections Framework Introduction
1. Java Collections Framework Introduction1. Java Collections Framework Introduction
1. Java Collections Framework Introduction
 
Intervies
InterviesIntervies
Intervies
 
The 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryThe 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summary
 
The 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summaryThe 23 gof design patterns in java ,the summary
The 23 gof design patterns in java ,the summary
 
Core_Java_Interview.pdf
Core_Java_Interview.pdfCore_Java_Interview.pdf
Core_Java_Interview.pdf
 
Opposites Attract
Opposites AttractOpposites Attract
Opposites Attract
 
Slide Dasar Materi Java Collection Framework
Slide Dasar Materi Java Collection FrameworkSlide Dasar Materi Java Collection Framework
Slide Dasar Materi Java Collection Framework
 
Review oop and ood
Review oop and oodReview oop and ood
Review oop and ood
 
Learn advanced java programming
Learn advanced java programmingLearn advanced java programming
Learn advanced java programming
 
Design Pattern Notes: Nagpur University
Design Pattern Notes: Nagpur UniversityDesign Pattern Notes: Nagpur University
Design Pattern Notes: Nagpur University
 
All 23 Design patterns in one page front and back
All 23 Design patterns in one page front and backAll 23 Design patterns in one page front and back
All 23 Design patterns in one page front and back
 

More from Kevlin Henney

The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical ExcellenceKevlin Henney
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical DevelopmentKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid DeconstructionKevlin Henney
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayKevlin Henney
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test CasesKevlin Henney
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to ImmutabilityKevlin Henney
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-InKevlin Henney
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good NameKevlin Henney
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Kevlin Henney
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantKevlin Henney
 

More from Kevlin Henney (20)

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
 
Get Kata
Get KataGet Kata
Get Kata
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good Name
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
 
Good Code
Good CodeGood Code
Good Code
 

Recently uploaded

英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 

Recently uploaded (20)

英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 

A Tale of Three Patterns

  • 1. 44 Java™ Report | OCTOBER 2001 http://www.javareport.com T HE CONTROL-FLOW structures of Java have remained fairly stable since their arrival in C three decades ago. They express the core structured- programming primitives of sequential, selective, and repetitive execution, as well as discontinuous control flow, such as breaking from a loop. Selective execution is much as it used to be, except it has lost some ground to the use of polymorphism. The basic refinement to sequential execution has been its disruption through exceptions and its multiplication through threading, both of which are supported in the heart of the language. My previous two columns1, 2 explored patterns that cap- tured differences in practice between single-threaded and multi-threaded programming, and exception-free and exception-throwing code. Iteration constructs have changed little since days of yore, but the subject of iteration has been objectified and pattern-enriched with collections and iterators. To begin at the beginning, there are five features that define any iteration: • The initialization to start the loop. • The continuation condition to keep it running (or termi- nation condition to stop it, depending on whether you regard the glass as half-full or half-empty). • The body of the loop to do the work. • The advancement of the iteration to go around again. This may be a distinct action, i.e., an increment, or a side effect of something in the body of the loop. • The finalization to clean up after the loop. This feature is often optional, a no-op. It is no coincidence that the four mandatory parts of a loop correspond to the anatomy of the for. The ITERATOR pattern3 represents what many OO devel- opers think of as the design for iteration in an object sys- tem, but there is more to iteration abstraction than just ITERATOR. The rest of this column looks at three iteration patterns whose solutions differ in their response to thread- ing, distribution, exceptions, and parameterization. So let’s start by looking in detail at something that should be fairly familiar. Iteration Pattern 1: ITERATOR Support iteration over an encapsulated collection by plac- ing responsibility for iteration into a separate object. Problem. How can elements of a collection be accessed conveniently, sequentially, and efficiently without exposing its underlying representation or making it less cohesive? If the representation of a collection is accessible, users can access the internal struc- ture of the object directly so they can iterate over it. However, users can under- mine its structure, intention- ally or otherwise, giving rise to subtle bugs or assumptions about undocumented class behavior. Their code is also strongly coupled to the imple- mentation details of the collection, so any changes to the data structure will inevitably break the client code, and any change of collection type will inevitably cause a rewrite. It is not possible to work reasonably through an interface if the implementation of a collection must be known in order to use it. It is tempting to use a conventional integer index to look up elements. However, this is an abstraction too far, hiding potentially expensive operations behind an inno- cent-looking interface. To loop over every element in an array-based sequence with an index is a linear-time oper- ation (O(N) in O-notation), with the generated code visit- ing each element precisely once in constant time. To do the same for a linked-list implementation is significantly more expensive (a pricey O(N2)) as previously visited links in the list are retraversed each time to find the next indexed element. To get a feel for what this means in practice, an array of 10 elements will require 10 accesses, whereas a list of 10 will require 55 link traversals. But where an array of 100,000 elements requires 100,000 accesses, a list of the same length requires more than 5 billion link traversals. Hiding such a profound difference between a random-access structure and a sequential- access structure behind a weakly specified get interface (no non-functional guarantees or warnings are given) is questionable design. In sequential-access cases, it can be more effective to make use of a toArray method to get a snapshot of all the elements and iterate over the returned array instead. However, this still requires the user to know the imple- Kevlin Henney is an independent consultant and trainer based in the UK. Kevlin Henney/kevlin@curbralan.com Patterns In Java Iteration constructs have changed little since days of yore, but the subject of iteration has been objectified and pattern-enriched with collections and iterators. A tale of three patterns
  • 2. http://www.javareport.com OCTOBER 2001 | Java™ Report 45 mentation type of the collection, and it is not without its own overhead. Iteration can be supported directly in the collection by providing the collection with the notion of a current position. Unfortunately, this restricts a collection to only a single iteration at a time. The methods of the collection cannot use the iteration mechanism for fear they may upset an existing iteration; a collection may be refer- enced by many objects, each with its own use for the notion of a “current position,” and there is therefore a strong possibility of interference between them. There is also a question of cohesion—or rather the lack of it— when a collection’s interface and implementation are asked to represent both a collection of items and a cur- rently selected item. Solution. Place responsibility for iteration into an object separate from the object being iterated over. The funda- mental features of iteration must be supported, with the most common division of features being for the collection to support creation and initialization of an iterator object, often using a FACTORY METHOD,3 and the iterator object itself supporting the traversal features, either as sepa- rate methods or as combined methods—COMMAND-QUERY SEPARATION vs. COMBINED METHOD.1 From the standard java.util package, the Iterator and Collection interface offer an example of the ITERATOR pattern in action: public interface Iterator { boolean hasNext(); Object next(); // Combined Method for advance and retrieve ... } public interface Collection { ... Iterator iterator(); // Factory Method ... } The underlying collection data structure is now fully hidden, but without hiding complexity costs from the user. There may be some additional overhead as a result of creating an additional object and adding a managed level of indirection. Whether this is significant depends on the task the iteration is being carried out for and the nature of the application. The user is now freed from any dependency on imple- mentation details—to the extent that a collection class may be modified without affecting the code, or an alternative collection type may be substituted, assuming an interface- based approach is taken. It is even possible for the collec- tion to be virtual in the sense there is no real collection of objects at all, i.e., objects on an input stream or objects that are calculated on the fly. There is coupling between the iterator and the collec- tion classes, suggesting the iterator class should be nested within the collection class definition. It may be as a public class in its own right or, more likely, a private inner or stat- ic class implementing an interface such as java.util.Iterator. If the iterator is simple, it may be reasonable to define it as an anonymous inner class within the body of the actual creation method. Multiple traversals can now be supported, but the ques- tion of validity arises if the collection is modified while the iteration is carried out. The decision has to be taken as to whether invalidating iterators is reasonable or not for a given design, and then what to do about it. • For small collections an iterator can take a snapshot of the collection’s contents, i.e., such as using toArray and iterate over that. This has the disadvantage of a costly initialization, but the advantage of guaranteeing itera- tion validity and content, even with multiple threads. • Another approach to managing iterator validity is to establish an OBSERVER relationship3 between the itera- tor and the collection, so that the iterator is notified of any changes in the collection, i.e., either invalidating itself or advancing itself an element if its current ele- ment is removed. • A version stamp can also be used, so the collection has a counter that is only modified when the collection structure is modified. An iterator remembers the ver- sion of its creation and always checks to see that the target collection has not changed. This approach is used in the Java Collections API, but has the disadvan- tage that any change—even one that would not invali- date the current iterator—will cause an exception to be thrown. • A more tolerant and laissez-faire approach is to only throw an exception when the iterator absolutely can- not perform an operation due to changes. For instance, increasing the size of an array-based collection need not invalidate iterators, but reducing the size below the index of the current iterator would. Removing ele- ments is generally safe from a linked list, and can also be made safe if the current element is removed—either the outgoing references continue to refer to adjacent links to allow iteration to continue, or the outgoing references are nulled, leading to an exception on the next advance. • The move to the next element, the extraction of the ele- ment, and the check that it is actually there can all be combined into a single method. This use of COMBINED METHOD1 ensures that the traversal aspects of the loop are uninterruptible and can be synchronized by the iter- ator rather than the user of the iterator. This technique can be combined with any of the strategies above. Note that although java.util.Iterator has a COMBINED METHOD, it does not fulfill the role just described. The separation of iteration from the interface of the collection means that collection users can customize their own iteration by adapting the raw iterator, i.e., defining a search iterator that skips elements that do not Patterns In Java
  • 3. match some particular condition when it traverses. Iteration Pattern 2: ENUMERATION METHOD Support encapsulated iteration over a collection by placing responsibility for iteration into a method on the collection. Problem. Some collection types have representations that do not conveniently support ITERATOR-based travers- al. How can elements of such a collection be sequentially and efficiently accessed without complicating and com- promising the implementation of the collection? For instance, a dictionary implemented as a sorted bina- ry tree can be implemented minimally with each tree node having a link to the child node on the left and on the right, plus the actual data element, and so on recursively down the subtrees. The subtree on the left has values that com- pare lower than the data element, while those in the sub- tree on the right compare higher: public class SortedBinaryTree { ... private static class Node { String key, value; Node left, right; } private Node root; } The simplest approach for visiting each element in order is to recurse through the subtree on the left before dealing with the key and value in the current node, and then recurse through the subtree on the right. However, this data structure will not easily support an iterator. The traversal is broken up, and the context for recursion is lost. One way to allow the iterator to retain context is to add a parent link so the iterator can navigate both up and down a tree: public class SortedBinaryTree { ... private static class Node { String key, value; Node left, right, up; } private Node root; } However, this complicates the management of the tree and adds a small overhead—sometimes insignificant—to each node. An alternative ITERATOR implementation does not require a parent link, and captures the depth context itself in a Stack: public class SortedBinaryTree { public class static Iterator implements java.util.Iterator { ... private java.util.Stack nodes; // nodes to revisit } ... } The stack places the complexity in the iterator rather than the collection, but can be fragile if the collection’s structure changes during iteration. In each case, there are further issues if something like the standard Iterator interface is used for a dictionary. It provides only for returning a single value, and so a com- bined data structure to represent the key-value pair must be used. Note that this problem does not arise if COMMAND- QUERY SEPARATION is used. More generally, there are times when a collection requires some pre- and post-iteration code to be executed before and after the traversal. The most obvious and com- mon case is synchronization against threaded interruption. Leaving users to do it for themselves is tedious and error prone and, specifically referring to thread synchronization, a synchronized block is problematic because it can give the illusion of safety without any of the safety.1 Solution. Bring the iteration inside the collection and encapsulate it in a single method responsible for complete traversal. The task of the loop—what would normally be its body—is passed in as a COMMAND object3 and is applied to each element in turn (see Listing 1). The method applies any of the relevant pre- and post- iteration actions itself, performing the loop in between, effectively atomically. Different loop strategies can be sup- ported easily by adding new methods, rather than requir- ing a whole new object type, i.e., for pre-order traversal. This is particularly useful for recursive data structures, such as COMPOSITE objects.3 The ENUMERATION METHOD4 is a fundamental iteration pattern that encapsulates the actual control flow of the traversal loop. There are strong similarities with the TEMPLATE METHOD design pattern,3 as well as VISITOR3 and EXECUTE-AROUND METHOD.2 ENUMERATION METHOD can be considered an inversion of the ITERATOR model, both in terms of its flow of control and responsibilities. The per- formance of an ENUMERATION METHOD is directly compara- ble to that of an ITERATOR. Iteration Pattern 3: BATCH METHOD Group multiple collection accesses together to reduce the cost of multiple individual accesses. Problem. How can many actions be treated atomically? In particular, how can multiple operations and accesses on a collection be handled efficiently and without interrup- tion? In a distributed system—or any other environment involving access latency, such as database access—iterated simple operations use up bandwidth: Patterns In Java 46 Java™ Report | OCTOBER 2001 http://www.javareport.com
  • 4. http://www.javareport.com OCTOBER 2001 | Java™ Report 47 for(each key of interest) { ... dictionary.put(key, value); } for(each key of interest) { value = dictionary.get(key); ... } While ITERATOR allows traversal of a sequence in an abstract and controlled fashion, it does not itself address concurrency and efficiency issues. A COMBINED METHOD addresses the basic concurrency issues, and can fold three operations into one; however, this only reduces the num- ber of accesses, not the number of times a cost-incurring loop is performed. Solution. Define a single method that performs the action repeatedly. The method is declared to take all the arguments for each execution of the action, i.e., an array or collection, and to return results by similar means. This single method folds the repetition into a data structure rather than a loop, so that looping is performed before or after the method call, in preparation or in follow up. Therefore, the cost of access is reduced to a single access, or a few “chunked” accesses: interface RemoteDictionary ... { Object[] get(Object[] keys); void put(Object[] keys, Object[] values); ... } Each method access is now more expensive, but the overall cost has been reduced. Such accesses can also be synchronized as appropriate within the method call. The trade-off in complexity is that significantly more house- keeping is performed to set up and work with the results of the call, and more intermediate data structures are required. The BATCH METHOD pattern is found in many distributed system architectures, such as the CORBA Common Object Services.5 It can be considered as taking the COMBINED METHOD pattern to its logical extreme in com- bining many iterations into a single shot. Conclusion What drives pattern-based design is not that patterns embody neat fragments of design—although this is often true—but that any given pattern can be considered in ten- sion with one or more other patterns. These other pat- terns compete as design alternatives, with the trade-offs in their forces and consequences making all the differ- ence, pulling the design one way and another. Sometimes there is a clear winner and the consideration of alterna- tives does not add anything except time spent mulling over the detail at the water cooler, on the whiteboard, or on the way home. However, at other times having a default case you always apply, without question, can have quite the opposite effect, accidentally brushing sig- nificant concerns under the carpet. It is here that having patterns presented together and in opposition captures more of the spirit of the design, even in something as humble and everyday as iteration. s References 1. Henney, K. “A Tale of Two Patterns,” Java Report, Vol. 5, No. 12, December 2000, available at http://www. curbralan.com. 2. Henney, K. “Another Tale of Two Patterns,” Java Report, Vol. 6, No. 3, March 2001, available at http://www. curbralan.com. 3. Gamma, E., et al. Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995. 4. Beck, K. Smalltalk Best Practice Patterns, Prentice Hall, 1997. 5. Object Management Group (OMG). CORBAservices: The Common Object Services Specification, available at http://www.omg.org. Patterns In Java Iteration over a sorted binary tree using recursive descent in an enumeration method public interface KeyValueTask { void apply(String key, String value); } public class SortedBinaryTree { public synchronized void forEachDo(KeyValueTask toDo) { forEachDo(toDo, root); } private void forEachDo(KeyValueTask toDo, Node node) { if(node != null) { forEachDo(toDo, node.left); toDo.apply(node.key, node.value); forEachDo(toDo, node.right); } } ... } tree.forEachDo(new KeyValueTask() { public void apply(String key, String value) { System.out.println(key + “ -> “ + value); } }); LISTING 1