One Day Mode - Iterator Mode

1. The concept of iterator mode

Provides a way to sequentially access various elements in an aggregated object without exposing its internal representation.

2. When to use the iterator mode

The scenario used by the iterator pattern is clear, that is, encapsulate traversal.

When a business traverses a data structure in your object, there are usually two ways to do this:

  • Return the data structure to the caller and let him iterate through it;
  • Reference iterator mode, encapsulate traversal;

Here's how to do it.

3. How to use the iterator mode

Explain through a business scenario or demonstrate using Java code.

Suppose you have two menus (system menu and business menu), which you need to traverse.First, let's see what's wrong with not using the iterator mode.

3.1 Disadvantages of not applying iterator mode

Join first developed business menu, data structure is array:

@Data
public class BusinessMenu {

    private String[] menus = new String[3];

    public BusinessMenu() {
        menus[0] = "Business Menu A";
        menus[1] = "Business Menu B";
        menus[2] = "Business Menu C";
    }

}

Then the system menu is developed, which is a data structure replaced by a collection:

@Data
public class SystemMenu {

    private List<String> menus = new ArrayList<>();

    public SystemMenu() {
        menus.add("System Menu 1");
        menus.add("System Menu 2");
        menus.add("System Menu 3");
    }

}

The traversed clients are then implemented as follows:

public class Client {

    public static void main(String[] args) {
        SystemMenu menus = new SystemMenu();
        List<String> mlist = menus.getMenus();
        printSystemMenu(mlist);
        System.out.println();
        BusinessMenu buttons = new BusinessMenu();
        String[] blist = buttons.getMenus();
        printBusinessMenu(blist);
    }

    public static void printSystemMenu(List<String> mlist) {
        for (int i = 0; i < mlist.size(); i++) {
            System.out.println(mlist.get(i));
        }
    }

    public static void printBusinessMenu(String[] blist) {
        for (int i = 0; i < blist.length; i++) {
            System.out.println(blist[i]);
        }
    }

}

This is what the second section says, returning the data structure to the caller so that he can traverse it, or more precisely, let him manipulate the data structure to traverse it.

This has two drawbacks:

  • Data security: If access to the data structure is not well controlled, callers cannot be restricted, which may cause damage to the data;
  • Low scalability: The code above writes two functions, printSystemMenu and printBusinessMenu, because the internal data structure is different, so the implementation is different. If there are other Menu objects and the internal data structure is not data or List, then a new traversal method is added, which does not compose the open-close principle, and is also a symptom of low scalability.

How do I use the iterator pattern to solve this problem?In fact, there is an iterator interface inside Java, and we can also create an iterator interface ourselves, as follows.

3.2 Use iterator mode to solve drawbacks

I'm going to implement this directly using the iterator interface provided by Java, but first look at the class diagram and code:

The code is as follows:

// System menu, iterator interface implemented
public class SystemMenu implements Iterator<String> {

    // Privatizing data structures
    private List<String> menus = new ArrayList<>();
    // Privateized Index
    private int index;

    public SystemMenu() {
        menus.add("System Menu 1");
        menus.add("System Menu 2");
        menus.add("System Menu 3");
        index = 0;
    }

    @Override
    public boolean hasNext() {
        // Determine if there are elements in the collection
        return index < menus.size();
    }

    @Override
    public String next() {
        // Returns the elements of a collection
        String name = menus.get(index);
        // Index+1
        index++;
        return name;
    }
}
// Business menu, iterator interface implemented
public class BusinessMenu implements Iterator<String> {

    // Privatizing data structures
    private String[] menus = new String[3];
    // Privateized Index
    private int index;

    public BusinessMenu() {
        menus[0] = "Business Menu A";
        menus[1] = "Business Menu B";
        menus[2] = "Business Menu C";
        index = 0;
    }

    @Override
    public boolean hasNext() {
        // Determine if there are elements in the array
        return index < menus.length;
    }

    @Override
    public String next() {
        // Returns elements from an array
        String name = menus[index];
        // Index+1
        index++;
        return name;
    }
}
public class Client {

    public static void main(String[] args) {
        printMenu(new SystemMenu());
        System.out.println();
        printMenu(new BusinessMenu());
    }

    public static void printMenu(Iterator<String> iterator) {
        // Using iterators, loop the output
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

}
Output:
System Menu 1
System Menu 2
System Menu 3

Business Menu A
Business Menu B
Business Menu C

The above is the iterator pattern, which is very simple. It is often used in daily development and many tool classes provide iterators for us to iterate through.

But still say how to solve the drawbacks:

  • Data security: Data structures are encapsulated inside objects and cannot be manipulated outside.
  • Encapsulate traversal: implements the iterator interface (generic) provided by Java, encapsulates the iteration steps into hasNext and next functions;

4. Summary

Iterator mode improves class cohesion!

Each responsibility of a class has potential areas for change.More than one responsibility means more than one change area.

This principle tells us to try to keep each class as single as possible.

Cohesion is a term used to measure whether a class or module closely achieves a single purpose or responsibility.

When a module or class is designed to support only one set of related functions, we say it has high cohesion; otherwise, when it is designed to support an unrelated set of functions, we say it has low cohesion.

Coherence is a more general concept than a single responsibility, but the relationship between them is very close.Classes that adhere to this principle are more likely to be highly cohesive and easier to maintain than low-within clusters with many responsibilities.

These are just some of my understanding of the iterator pattern. There are some deficiencies. Please point out that thank you.

Tags: Programming Java

Posted on Tue, 05 May 2020 18:10:46 -0700 by Aeolus