Category: Behavioral design patterns

Purpose: When the internal data structure of an object is changed, the external iteration behavior of the object is not changed, so as to reduce the external code changes caused by data structure changes

1drv.ms/u/s! AquRvPz…

A typical scenario

For example, the Editor to save the history content, business scenarios need to fetch all the history records for loop processing, generally provide a method in the Editor to return all the history content

Editor.java is referenced as follows:

public class Editor {
    private List<String> contentHistory = new ArrayList<>();

    public void push(String content) {
        contentHistory.add(content);
    }

    public String pop(a) {
        return contentHistory.remove(contentHistory.size() - 1);
    }
    
    public List<String> getContentHistory(a) {
        returncontentHistory; }}Copy the code

The code reference for the corresponding loop history is as follows:

var editor = new Editor();

for (int i = 0; i < editor.getContentHistory().size(); i ++) {
    System.out.println("content: " + editor.getContentHistory().get(i));
}
Copy the code

At this point, all the above methods are ok, but if the List

contentHistory changes the data type to private String[] contentHistory = new String[10]

public class Editor {
    // ...
    private String[] contentHistory = new String[10];
    public String[] getContentHistory() {
        return contentHistory;
    }
    // ...
}
Copy the code

The above loop will need to be adjusted as the data type changes:

var editor = new Editor();
for (int i = 0; i < editor.getCount(); i ++) {
    System.out.println("content: " + editor.getContentHistory()[i]);
}
Copy the code

The iterator pattern can be used when the editor history is referenced many times, say dozens of times, and the cost of the code adjustment is significant

Pattern implementation

Define the iterator interface

public interface Iterator {
    boolean hasNext(a); // Determine whether the data structure being looped has reached the end of the loop

    String current(a); // Get the current loop to the data

    void next(a); // Get ready to fetch the next data
}
Copy the code

The contentHistory data structure is then returned wrapped in the implementation class of the iterator interface, using the iterator to loop through the contentHistory, For example, private String[] contentHistory = New String[10] implements iterators as follows

public class ArrayIterator implements Iterator {
    private Editor editor;
    private int count;

    public ArrayIterator(Editor editor) {
        this.editor = editor;
    }

    @Override
    public boolean hasNext(a) {
        return (count < editor.getCount());
    }

    @Override
    public String current(a) {
        return editor.getContentHistory()[count];
    }

    @Override
    public void next(a) { count++; }}Copy the code

The usage mode is as follows:

var editor = new Editor();
Iterator iterator = editor.createIterator(); // Notice the Iterator interface Iterator

while (iterator.hasNext()) {
    System.out.println("content: " + iterator.current());
    iterator.next();
}
Copy the code

If the contentHistory data structure changes, the iterator can be modified inside the iterator to accommodate the new data structure, without affecting the caller using the Iterator interface. This reduces the need for repeated code changes

List

contentHistory iterator

public class ListIterator implements Iterator {
    private Editor editor;
    private int count;

    public ListIterator(Editor editor) {
        this.editor = editor;
    }

    @Override
    public boolean hasNext(a) {
        return count < editor.getContentHistory().size();
    }

    @Override
    public String current(a) {
        return editor.getContentHistory().get(count);
    }

    @Override
    public void next(a) { count++; }}Copy the code

As you can see, where you use a data structure, you rely on the Iterator interface. As long as the data structure implements the Iterator interface, you don’t need to change the user

UML

Why is iterator mode better

Uncouple code that needs to be adjusted due to data structure changes into the iterator interface, reducing the maintenance cost of data structure changes

A couple of points to note

Iterator implementations can use inner classes

The resources

  1. Java-design-patterns.com/patterns/it…