Design Patterns

Iterator



Design Pattern Type: Behavioral

GoF Statement of Intent:


Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
Brief Overview:



Iterators let you access elements in a collection of objects with functions like hasNext() to see if there is another object in the collection and getNext() to get a pointer to that object. This way you have a common way of accessing all elements without having to know how the underlying collection is implemented, i.e. list, array, tree, etc.
UML Diagram:

Discussion and In-class Example:

The Iterator Design Pattern is the one which some students may be familiar with but didn't know it was a Design Pattern. In the templates found in the Standard Template Library all of the collection templates have implemented an Iterator which allows the user to loop through each item in the collection one at a time. The primary objective is that this allows us to loop through every item in the collection, but it hides the actual implementation of the collection.

The example we used in class for the Iterator was the menus for the Objectville Pancake House and the Objectville Cafe. Both used a collection of MenuItem objects to store their menus, but the Pancake House used an ArrayList to store its collection of MenuItems while the Cafe used an Array. Without the use of an Iterator any class (like Flo the waitress) would have to know the internal structure of the Pancake House and the Cafe menus to be able to loop through them. But, by creating a MenuIterator parent class to serve as the Interface we can subclass that to create a PancakeHouseMenuIterator and a CafeMenuIterator. Now we can use the functions hasNext() and next() to loop through all MenuItems in both without having to know anything about the internal structure. It also means we could change the internal structure of our collections, create a new MenuIterator type to handle the new collection and nothing outside those classes will have to change in our application.



Implementation of Waitress using Iterators
class Waitress
{
     private:
          PancakeHouseMenu *pancakeHouseMenu;
          CafeMenu *cafeMenu;
     public:
         Waitress(PancakeHouseMenu *phm, CafeMenu *cm)
          {
               this->pancakeHouseMenu=phm;
               this->cafeMenu = cm;
          }
          void printMenus()
          {
               MenuIterator *phIterator = pancakeHouseMenu->getIterator();
               Iterator *cIterator = cafeMenu->getIterator();
               cout << "MENU\n----\nBREAKFAST";
               printMenu(phIterator);
               cout << "MENU\n----\nLunch";
               printMenu(cIterator);
          }
          void printMenu(Iterator *itr)
          {
               while(itr->hasNext)
               {
                    MenuItem *menuItem = itr->next();
                    menuItem->print();
               }
          }
}