Iterator Design Pattern - Java
History Coding Kata
All Web Browsers keep history of websites a user is visiting. And they also provide facility to go back and forth by clicking left or right arrows.
Lets write a program to simulate this feature. Program should provide methods to store
and remove
website urls and also provide a mechanism to loop through and print the history.
Program should be easy to maintain. Client code should not depend on the inner working details.
First Step
Write a program without using any design patterns. This is an important step. Wihout this step, if you directly jump to deisgn pattern then you will not know what problem the design pattern is solving, so do not skip this step
Example:
- Create a class
BrowseHistory
- Use a List of Strings
List<String>
data structure to store the urls - Provide
push
andpop
methods to store or remove urls from the list - Client program uses
push
andpop
methods ofBrowseHistory
class to store or remove the urls from history - Client program uses a
for loop
to irerate through the history
- Create a class
Disadvantages with above approach
- A change in data structure will affect the client code
- Ex: If we decide to use a fixed size array like
String[]
instead ofList<String>
thenfor loop
breaks, because looping throughString[]
would require a different logic. This means a breaking change to client code.
Applying Iterator Design Patterrn
Overview of Implementation
Instead of the client program directly depending on the concrete implementation, we can use an interface
to decouple the client code from internal details.
Lets say BrowseHistory
is the class used by the client to store, retrieve and loop through the history of urls.
Client will ask the BrowseHistory
to give an iterator, ex: createIterator()
method and then uses the interface methods
of the iterator object to iterate through the list. In future if we decide to use a different data structure then it will not break the client code because the client is using an interface which means not depending on implementation details.
Detail Steps
- Create an interface
// pseudo code
interface Iterator {
boolean hasNext() // tells if there are any more items in the list
void next() // advances the index
String current() // returns current item
}
In the above interface, client is expected to use
String
type for the urls.We can further remove this dependency by using
Generics
Creating a generic interface
// pseudo code
interface Iterator<T> {
boolean hasNext() // tells if there are any more items in the list
void next() // advances the index
T current() // returns current item
}
In the above interface, type is indicated by
T
, and it is decided during run timeThis gives flexibility to client. Client can use
String
or any other supported types. Client can ask for specific type of iterator. For ex:createStringIterator() // type is String
createCookieIterator() // type is Cookie
- etc..
Depending on what the client asks for,
BrowseHistoy
will provide that specific iterator to the clientThe way to iterate is same for any type, so no change in code on client needed for the actual iteration process.
Use an Inner Class ex:
class ListIterator
to implement the interface. This is because iterrator requires access to the history and using an inner class we can avoid exposing the history outside ofBrowseHistory
class.If we change the implementation from
List
toString[]
then we need to update only theBrowseHistory
class. Client code is not affected by this change, it is an implementation detail.
How to run the programs ?
Implement using List<String>
Clone GitHub repository
git@github.com:smarigowda/IteratePatternJava.git
Run the main program
Change the implementation to use Stting[] to prove that it does not affect client code
Clone GitHub repository
git@github.com:smarigowda/IteratePatternJava.git
Change branch
git checkout exercise-string-array
Run the main program