Transcript Notes

Iterator Pattern
Traversing two
different collections
 When bringing two previously
developed objects together, it
can be difficult to change an
implementation
 Diner merger with PancakeHouse
 Menu items -- same for both
collections -- this is key
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("Steamed Veggies and Brown Rice",
"Steamed vegetables over brown rice", true, 3.99);
addItem(…)
}
public void addItem(String name, String description,
boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.err.println("Sorry, menu is full! Can't add item to menu");
} else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
// other menu methods here
}
public class PancakeHouseMenu implements Menu {
ArrayList menuItems;
public PancakeHouseMenu() {
menuItems = new ArrayList();
addItem("K&B's Pancake Breakfast",
"Pancakes with scrambled eggs, and toast",
true,
2.99);
…
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public ArrayList getMenuItems() {
return menuItems;
}
// other menu methods here
}
public class Waitress {
PancakeHouseMenu pancakeHouseMenu;
ArrayList breakfastItems;
DinerMenu dinerMenu;
MenuItems[] lunchItems;
public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
breakfastItems = pancakeHouseMenu.getMenuItems();
this.dinerMenu = dinerMenu;
lunchItems = dinerMenu.getMenuItems();
}
public void printMenu(){
for (int i = 0; breakfastItems.size(); i++) {
MenuItem menuItem = (MenuItem)breakfastItems.get(i);
System.out.println(menuItem.getName()+” “+menuItem.getPrice());
System.out.println(menuItem.getDescription());
}
for (int i = 0; lunchItems.length; i++) {
MenuItem menuItem = lunchItems[i];
System.out.println(menuItem.getName()+” “+menuItem.getPrice());
System.out.println(menuItem.getDescription());
}
}
}
Waitress code
 Need two loops to go through
the two collections
 Will need to add another loop if
we add another collection
later
 waitress has to know intimate
details of the collection code -bad form!
Let’s Encapsulate!
 We can encapsulate the
iteration to avoid sharing too
much information
Iterator Interface
public interface Iterator
{
boolean hasNext();
Object next();
}
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
public Object next() {
MenuItem menuItem = items[position];
position = position + 1;
return menuItem;
}
public boolean hasNext() {
if (position >= items.length || items[position] == null) {
return false;
} else {
return true;
}
}
}
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
//constructor here
//addItem here
/* don’t need getMenuItems now that we have an Iterator!
public MenuItem[] getMenuItems() {
return menuItems;
}*/
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
// other menu methods here
}
New Waitress Code
public class Waitress {
PancakeHouseMenu pancakeHouseMenu;
DinerMenu dinerMenu;
public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
System.out.print(menuItem.getName() + ", ");
System.out.print(menuItem.getPrice() + " -- ");
System.out.println(menuItem.getDescription());
}
}
//other methods
}
Compare and contrast
Waitresses
Old
Waitress must know
about menu
implementation
Needs 2 loops
new
Menus are
encapsulated
Waitress bound to
concrete classes
(MenuItem[] and
ArrayList)
Waitress now uses an
interface (Iterator)
Need 1 loop
Java.util.iterator
 Now that we’ve built an iterator
from scratch, we can learn about
Java’s Iterator interface
 hasNext()
 Next()
 remove()
 Optional -- in unsupported must
throw
 Java.lang.unsupportedOperationExc
eption
Updating menus
import java.util.ArrayList;
import java.util.Iterator;
public class PancakeHouseMenu implements Menu {
ArrayList menuItems;
//constructor here
public Iterator createIterator() {
return menuItems.iterator();
}
// other menu methods here
}
ArrayList already implements the Iterator interface
import java.util.Iterator;
public class DinerMenuIterator implements Iterator {
MenuItem[] list;
int position = 0;
public DinerMenuIterator(MenuItem[] list) {//constructor here }
public Object next() { //current implemenation }
public boolean hasNext() { //current implementation }
public void remove() {
if (position <= 0) {
throw new IllegalStateException
("You can't remove an item until you've done at least one
next()");
}
if (list[position-1] != null) {
for (int i = position-1; i < (list.length-1); i++) {
list[i] = list[i+1];
}
list[list.length-1] = null;
}
}
}
Updating waitress with
menu interface
public interface Menu{
public Iterator createIterator();
}
Add “implements Menu” to
DinerMenu and
PancakeHouseMenu
Then…
import java.util.Iterator;
public class Waitress {
Menu pancakeHouseMenu;
Menu dinerMenu;
public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
System.out.print(menuItem.getName()+", ”+menuItem.getPrice()+ " -- ");
System.out.println(menuItem.getDescription());
}
}
//other methods
}
definitions
 The Iterator Pattern provides a way
to access the elements of an
aggregate object sequentially
without exposing its underlying
representation.
 Aggregate object - an object that is
a collection of other objects of the
same type, intended primarily for
storage
<<interface>>
Aggregate
createIterator()
Client
<<interface>>
Iterator
hasNext()
next()
remove()
ConcreteAggregate
ConcreteIterator
createIterator()
createIterator()
Iterator faq
 Backwards iteration
 Yes, but you need to add some
methods. Which?
 Java also has ListIterator, similar
 Ordering
 Iterator does not imply ordering
Design Principle
sinlge responsibility
 A class should have only one
reason to change
 An aggregate that manages its own
collection AND iteration has two
opportunities to change.
 Where?
Cohesion
 A measure of how closely a
class supports a single purpose
or responsibility
 High cohesion: designed around
a set of related functions
 Low cohesion: designed around
unrelated functions
Cohesion examples
 Book pg. 340
Iterator and Hashtable
 Hash table accesses Iterator
indirectly
import java.util.*;
public class CafeMenu implements Menu {
Hashtable menuItems = new Hashtable();
public CafeMenu() {
//constructor code here
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description,
vegetarian, price);
menuItems.put(menuItem.getName(), menuItem);
}
public Iterator createIterator() {
return menuItems.values().iterator();
}
}
Iterators and
Collections




Java Colleections Framework
Vector, LinkedLIST, Stack, etc.
Java.util.collection interface
Each collection object knows
how to create its own iterator!
Sweet!
<<interface>>
Collection
add()
addAll()
clear()
contains()
containsAll()
equals()
hashCode()
isEmpty()
iterator()
remove()
removeAll()
reatainAll()
size()
toArray()
For/in is the new for
 With java5 we have a new syntax
for iterating over collections
 For(Object obj: collection)
 No need to get the iterator
 Generics
 Type security
Composite
 Iterator is related to the
Composite Pattern
 We are not going to cover it
this semester, but you can read
about it in your book.