Design Patterns_Behavioral Patterns-《Iterator Patterns》

Design Patterns_Behavioral Patterns-《Iterator Patterns》

The notes are organized from the detailed explanation of Java design patterns by dark horse programmers, 23 Java design patterns (diagram + framework source code analysis + actual combat)

overview

definition

  • Provides an object to sequentially access a range of data in an aggregate object without exposing the aggregate object's internal representation.

structure

Iterator Pattern mainly includes the following roles:

  • Abstract Aggregate (Aggregate) role: defines the interface for storing, adding, and removing aggregated elements, and creating iterator objects.

  • Concrete Aggregate role: implement an abstract aggregate class and return an instance of a concrete iterator.

  • Abstract iterator (Iterator) role: defines the interface for accessing and traversing aggregate elements, usually including hasNext(), next() and other methods.

  • Concrete iterator (Concrete iterator) role: implement the method defined in the abstract iterator interface, complete the traversal of the aggregated object, and record the current position of the traversal.

Case realization

[Example] Define a container object that can store student objects, and hand over the function of traversing the container to an iterator. The classes involved are as follows:

code show as below:

  • Abstract iterator role - iterator interface, declares hasNext(), next() methods

    public interface StudentIterator {
          
          
        
        // 判断是否还有元素
        boolean hasNext();
        
        // 获取下一个元素
        Student next();
    }
    
  • Concrete iterator role class, overriding all abstract methods

    public class StudentIteratorImpl implements StudentIterator {
          
          
        private List<Student> list;
        private int position = 0; // 记录遍历时的位置
    
        public StudentIteratorImpl(List<Student> list) {
          
          
            this.list = list;
        }
    
        // 判断是否还有元素
        @Override
        public boolean hasNext() {
          
          
            return position < list.size();
        }
    
        // 获取下一个元素
        @Override
        public Student next() {
          
          
            // 从集合中获取指定位置的元素
            Student currentStudent = list.get(position);
            position++;
            return currentStudent;
        }
    }
    
  • Abstract container class (abstract aggregation role), including methods for adding elements, removing elements, and obtaining iterator objects

    public interface StudentAggregate {
          
          
        
        // 添加学生功能
        void addStudent(Student student);
    
        // 删除学生功能
        void removeStudent(Student student);
        
        // 获取迭代器对象功能
        StudentIterator getStudentIterator();
    }
    
  • Concrete container class (concrete aggregate role), override all methods

    public class StudentAggregateImpl implements StudentAggregate {
          
          
    
        private List<Student> list = new ArrayList<Student>(); // 学生列表
    
        // 添加学生功能
        @Override
        public void addStudent(Student student) {
          
          
            this.list.add(student);
        }
    
        // 删除学生功能
        @Override
        public void removeStudent(Student student) {
          
          
            this.list.remove(student);
        }
    
        // 获取迭代器对象功能
        @Override
        public StudentIterator getStudentIterator() {
          
          
            // 创建迭代器对象
            return new StudentIteratorImpl(list);
        }
    }
    
  • student class

    public class Student {
          
          
        private String name;
        private String number;
        
        // getter/setter...
        
        public Student(String name, String number) {
          
          
            this.name = name;
            this.number = number;
        }
        
        @Override
        public String toString() {
          
          
            return "Student{" +
                    "name='" + name + '\'' +
                    ", number='" + number + '\'' +
                    '}';
        }
    }
    
  • test class

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            // 创建聚合对象
            StudentAggregateImpl aggregate = new StudentAggregateImpl();
            // 添加元素
            aggregate.addStudent(new Student("张三", "001"));
            aggregate.addStudent(new Student("李四", "002"));
            aggregate.addStudent(new Student("王五", "003"));
            aggregate.addStudent(new Student("赵六", "004"));
    
            /*
             * 遍历聚合对象
             */
    
            // 1.获取迭代器对象
            StudentIterator iterator = aggregate.getStudentIterator();
            // 2.遍历
            while (iterator.hasNext()) {
          
          
                // 3.获取元素
                Student student = iterator.next();
                System.out.println(student.toString());
            }
        }
    }
    

    output

    Student{name='张三', number='001'}
    Student{name='李四', number='002'}
    Student{name='王五', number='003'}
    Student{name='赵六', number='004'}
    

Advantages and disadvantages

advantage

  • It supports traversing an aggregate object in different ways, and multiple traversal methods can be defined on the same aggregate object. In the iterator mode, we only need to replace the original iterator with a different iterator to change the traversal algorithm. We can also define subclasses of iterators to support new traversal methods.
  • Iterators simplify aggregation classes. Due to the introduction of iterators, there is no need to provide methods such as data traversal in the original aggregation objects, which can simplify the design of aggregation classes.
  • In the iterator mode, due to the introduction of the abstraction layer, it is very convenient to add new aggregation classes and iterator classes without modifying the original code, which meets the requirements of the "opening and closing principle".

shortcoming

  • The number of classes has been increased, which increases the complexity of the system to a certain extent.

scenes to be used

  • When you need to provide multiple traversal methods for aggregate objects.
  • When it is necessary to provide a unified interface for traversing different aggregation structures.
  • When accessing the contents of an aggregate object without exposing its representation of internal details.

JDK source code analysis - collection class

The iterator mode is widely used in many collection classes of java, let's see how the iterator mode is used in the java source code.

List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator(); // list.iterator()方法返回的肯定是Iterator接口的子实现类对象
while (iterator.hasNext()) {
    
    
    System.out.println(iterator.next());
}

After reading this code, is it familiar to you? It is basically similar to our code above. All single-column collections use iterators. Let's take ArrayList as an example:

  • List: abstract aggregation class
  • ArrayList: concrete aggregation class
  • Iterator: abstract iterator
  • list.iterator(): Returns Iteratora specific iterator object that implements the interface (in ArrayList, it is the internal class Itr)

Take a look at the code implementation of ArrayList specifically:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    
    
    public Iterator<E> iterator() {
    
    
        // 返回的肯定是Iterator的子实现类对象
        return new Itr();
    }
    			   ||
                   \/
    // 内部类Itr 实现了Iterator接口 并且重写了 hasNext() 和 next() 方法。
    private class Itr implements Iterator<E> {
    
    
        int cursor;       // 下一个要返回元素的索引
        int lastRet = -1; // 上一个返回元素的索引
        int expectedModCount = modCount;

        Itr() {
    
    }
		
        // 判断是否还有元素
        public boolean hasNext() {
    
    
            return cursor != size;
        }

        // 获取下一个元素
        public E next() {
    
    
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        ...
}

This part of the code is relatively simple, roughly, iteratoran instantiated Iteratorobject is returned in the method, Itr is an inner class, which implements Iteratorthe interface and rewrites the abstract method in it.

Notice:

When we are developing in java, if we want to use the iterator mode, we only need to let our self-defined container class implement java.util.Iterableand implement the iterator() method in it to return an java.util.Iteratorimplementation class of .

Guess you like

Origin blog.csdn.net/weixin_53407527/article/details/128628099