Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Java Tip 38: The trick to "Iterator Observers"

Factor out common code and make your Iterators observable

  • Print
  • Feedback
On this month's tip we will take a brief look at the Iterator and Observer design patterns and then go on to examine how to use these patterns together to create Iterator Observers. Readers familiar with these two patterns may want to move straight to the section called Iterator Observers.

Iterators

Iterators provide an abstract mechanism to access elements in collection classes without revealing their underlying representations. A collection class is a class that can contain a number of items in a certain data structure such as linked lists and hash tables. An example of a collection class is java.util.Vector.

The first two listings explore why hiding the underlying representation of a collection class helps reduce the level of coupling between classes. The following enumeration is an example of an iterator in Java:

public  interface  java.util.Enumeration
{    public abstract boolean hasMoreElements();    public abstract Object nextElement();
}


If used correctly, Iterators promote loose coupling between collection classes and their clients. Listing 1 illustrates a poor use of an Iterator.

public class Display extends Panel
{
    private List itemList= new List();
    public Display()
    {
        add( itemList );
    }
    public void InitList( Vector opts )
    {
        Enumeration e=opts.elements();
        while( e.hasMoreElements()  )   
        {
            String item=(String)e.nextElement();
            itemList.addItem( item );
        }
    }
}


Listing 1: A poor use of an Iterator

So why have I said that the approach used in Listing 1 is poor? InitList() is coupled to the use of a Vector. Consider the impact and effort involved if your system contains many dependencies on a particular collection class -- in this case Vector -- and you later need to change it to your own class or a third-party class that suits your system better. So how can we improve this design? Listing 2 shows how, by using polymorphism and passing an iterator as a parameter rather than a Vector, class Display can be used by any client with a collection class that supports the Enumeration interface. Class Test demonstrates this by passing either a Vector or a hashtable's Enumeration to the Display object. (For more information on abstraction and polymorphism, see my JavaWorld article, "Polymorphism and Java.")

public class Display extends Panel
{
    //as listing 1
    public void InitList( Enumeration e )
    {
        while( e.hasMoreElements()  )   
        {
            String item=(String)e.nextElement();
            itemList.addItem( item );
        }
    }
}
public class Test
{
    private Vector      v   = new Vector();
    private Hashtable   ht   = new Hashtable();
    private Display         disp      = new Display();
    public void WithVector()
    {
        disp.InitList( v.elements() );
    }
    public void WithHashTable()
    {
        disp.InitList( ht.elements() );
    }
}


Listing 2: Improved usage of Iterator

Those readers who are interested in experimenting with Iterators should write a class that can read a row at a time from a text file, or even better from a database table, and provides an iterator over the rows in the form of the java.util.Enumeration interface. An example using JDBC occurs later in this article.

  • Print
  • Feedback

Resources