Design Patterns - Iterator Patterns

Keywords: Java

1. Summary of iterator patterns

Definition: Provides a method for sequentially accessing elements of an aggregated object without exposing its internal representation.

For example, when integrating the code of multiple objects at the same time, each object uses a different data structure. If you want them to be presented uniformly, you can use the iterator pattern.

Iterators are traversed forward and backward, and iterators don't care what data structures they use.

2. Examples of iterator patterns

The breakfast and lunch restaurants in Target Village have been merged. Now they need to merge their menus. But the menus of breakfast restaurants are in Array List. The menus of lunch restaurants are in array form. How can we show them in a unified way?

Let's see how the breakfast shop works first.

public class BreakFast {
    ArrayList<Menu> menus;

    public BreakFast() {
        menus = new ArrayList<>();
        addMenu("Deep-Fried Dough Sticks","Traditional Northern Breakfast",true,2.0);
        addMenu("Mixed congee","Various Food Combinations",true,2.0);
        addMenu("Egg cake","Traditional breakfast",true,5.0);
    }

    public void addMenu(String name,String description,boolean vegetarian,double price){
        Menu menu = new Menu(name, description, vegetarian, price);
        menus.add(menu);
    }

    public ArrayList getMenu(){
        return menus;
    }
}

Let's see how the lunch shop works.

public class Lunch {
    Menu[] menus;
    int numIndex = 0;

    public Lunch(Menu[] menus) {
        menus = new Menu[6];
        addMenu("Kung Pao Chicken","Chicken and chili with peanuts",false,25.0);
        addMenu("Pork braised in brown sauce","Pork braised in soy sauce",false,34);
        addMenu("Remember back in that day","Vegetable stir-fried cabbage",true,12);
        addMenu("Scrambled egg with tomato","Red with yellow",true,20);
    }

    public void addMenu(String name,String description,boolean vegetarian,double price){
        Menu menu = new Menu(name, description, vegetarian, price);
        menus[numIndex] = menu;
        numIndex++;
    }

    public Menu[] getMenus(){
        return menus;
    }
}

getMenus in both classes returned their respective data types, but that's not what we want, because we can't handle them with uniform code (foreach is possible, of course, but the main thing we need to know here is the iterator pattern).

For example, we have to deal with them.

public static void main(String[] args) {
    BreakFast breakFast = new BreakFast();
    Lunch lunch = new Lunch();

    ArrayList<Menu> breakFasts = breakFast.getMenu();
    Menu[] lunchs = lunch.getMenus();
    System.out.println("-----------------Here is breakfast.----------------------");
    for (int i = 0; i < breakFasts.size(); i++) {
        Menu menu = breakFasts.get(i);
        System.out.println(menu.getName() + " ");
        System.out.println(menu.getDescription() + " ");
        System.out.println(menu.getPrice() + " ");
    }
    System.out.println("-----------------Here is lunch.----------------------");
    for (int i = 0; i < lunchs.length; i++) {
        Menu menu = lunchs[i];
        System.out.println(menu.getName() + " ");
        System.out.println(menu.getDescription() + " ");
        System.out.println(menu.getPrice() + " ");
    }
}

By using the for loop, if you have an extra dinner, you need to add a little more code and use the for loop again.

To solve this problem, we introduce the iterator pattern. We use an iterator to make the data have the same return structure.

Iterator Interface

public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
}

This is the interface of iterator implementation provided by java. I don't talk much about it here. I believe all the students who have studied the set framework know the function of iterator.

We only need to implement the iterator interface to transform the above code into the same and reusable code.

public class BreakFast implements Iterable {
    ArrayList<Menu> menus;

    public BreakFast() {
        menus = new ArrayList<>();
        addMenu("Deep-Fried Dough Sticks","Traditional Northern Breakfast",true,2.0);
        addMenu("Mixed congee","Various Food Combinations",true,2.0);
        addMenu("Egg cake","Traditional breakfast",true,5.0);
    }

    public void addMenu(String name,String description,boolean vegetarian,double price){
        Menu menu = new Menu(name, description, vegetarian, price);
        menus.add(menu);
    }
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    @Override
    public Iterator iterator() {
        return menus.iterator();
    }
}

In this way, after invoking the iterator method, we can easily get the menu of iterator mode.

In the test code, we only need to make minor changes.

public static void main(String[] args) {
    BreakFast breakFast = new BreakFast();
    Lunch lunch = new Lunch();

    Iterator iterator = breakFast.iterator();
    Menu[] lunchs = lunch.getMenus();
    System.out.println("-----------------Here is breakfast.----------------------");
    while (iterator.hasNext()){
        Menu menu = (Menu) iterator.next();
        System.out.println(menu.getName() + " ");
        System.out.println(menu.getDescription() + " ");
        System.out.println(menu.getPrice() + " ");
    }
    System.out.println("-----------------Here is lunch.----------------------");
    for (int i = 0; i < lunchs.length; i++) {
        Menu menu = lunchs[i];
        System.out.println(menu.getName() + " ");
        System.out.println(menu.getDescription() + " ");
        System.out.println(menu.getPrice() + " ");
    }
}

Here, we just need to call the iterator's method, and we no longer need to know what its data structure is, so that we can hide the data type and traverse all the elements.

Posted by safetguy on Wed, 15 May 2019 17:25:36 -0700