Patrones de diseño_Patrones de comportamiento-《Patrones de iterador》

Patrones de diseño_Patrones de comportamiento-《Patrones de iterador》

Las notas están organizadas a partir de la explicación detallada de los patrones de diseño de Java por programadores de caballos oscuros, 23 patrones de diseño de Java (diagrama + análisis de código fuente del marco + combate real)

descripción general

definición

  • Proporciona un objeto para acceder secuencialmente a un rango de datos en un objeto agregado sin exponer la representación interna del objeto agregado.

estructura

Iterator Pattern incluye principalmente los siguientes roles:

  • Función Abstract Aggregate (Agregado): define la interfaz para almacenar, agregar y eliminar elementos agregados y crear objetos iteradores.

  • Función Agregado concreto: implementa una clase agregada abstracta y devuelve una instancia de un iterador concreto.

  • Rol de iterador abstracto (Iterator): define la interfaz para acceder y atravesar elementos agregados, que generalmente incluye hasNext(), next() y otros métodos.

  • Rol de iterador concreto (iterador concreto): implementa el método definido en la interfaz del iterador abstracto, completa el recorrido del objeto agregado y registra la posición actual del recorrido.

Realización de casos

[Ejemplo] Defina un objeto contenedor que pueda almacenar objetos de estudiante y transfiera la función de atravesar el contenedor a un iterador. Las clases involucradas son las siguientes:

el código se muestra a continuación:

  • Rol de iterador abstracto: interfaz de iterador, declara los métodos hasNext(), next()

    public interface StudentIterator {
          
          
        
        // 判断是否还有元素
        boolean hasNext();
        
        // 获取下一个元素
        Student next();
    }
    
  • Clase de rol de iterador concreto, anulando todos los métodos abstractos

    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;
        }
    }
    
  • Clase de contenedor abstracto (función de agregación abstracta), incluidos métodos para agregar elementos, eliminar elementos y obtener objetos iteradores

    public interface StudentAggregate {
          
          
        
        // 添加学生功能
        void addStudent(Student student);
    
        // 删除学生功能
        void removeStudent(Student student);
        
        // 获取迭代器对象功能
        StudentIterator getStudentIterator();
    }
    
  • Clase de contenedor concreto (función de agregado concreto), anula todos los métodos

    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);
        }
    }
    
  • clase de estudiante

    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 + '\'' +
                    '}';
        }
    }
    
  • clase de prueba

    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());
            }
        }
    }
    

    producción

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

Ventajas y desventajas

ventaja

  • Admite atravesar un objeto agregado de diferentes maneras, y se pueden definir múltiples métodos transversales en el mismo objeto agregado. En el modo iterador, solo necesitamos reemplazar el iterador original con un iterador diferente para cambiar el algoritmo transversal. También podemos definir subclases de iteradores para admitir nuevos métodos transversales.
  • Los iteradores simplifican las clases de agregación. Debido a la introducción de iteradores, no es necesario proporcionar métodos como el cruce de datos en los objetos de agregación originales, lo que puede simplificar el diseño de las clases de agregación.
  • En el modo de iterador, debido a la introducción de la capa de abstracción, es muy conveniente agregar nuevas clases de agregación y clases de iterador sin modificar el código original, lo que cumple con los requisitos del "principio de apertura y cierre".

defecto

  • Se ha aumentado el número de clases, lo que aumenta en cierta medida la complejidad del sistema.

Escenas a utilizar

  • Cuando necesite proporcionar múltiples métodos transversales para objetos agregados.
  • Cuando es necesario proporcionar una interfaz unificada para atravesar diferentes estructuras de agregación.
  • Al acceder al contenido de un objeto agregado sin exponer su representación de detalles internos.

Análisis de código fuente JDK - clase de colección

El modo iterador se usa ampliamente en muchas clases de colección de Java, veamos cómo se usa el modo iterador en el código fuente de Java.

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

Después de leer este código, ¿te resulta familiar? Es básicamente similar a nuestro código anterior. Todas las colecciones de una sola columna usan iteradores.Tomemos ArrayList como ejemplo:

  • Lista: clase de agregación abstracta
  • ArrayList: clase de agregación concreta
  • Iterador: iterador abstracto
  • list.iterator(): Devuelve Iteratorun objeto iterador específico que implementa la interfaz (en ArrayList, es la clase interna Itr)

Eche un vistazo a la implementación del código de ArrayList específicamente:

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];
        }
        ...
}

Esta parte del código es relativamente simple, aproximadamente, se devuelve iteratorun objeto instanciado en el método, Itr es una clase interna, que implementa la interfaz y reescribe el método abstracto en ella.IteratorIterator

Aviso:

Cuando estamos desarrollando en Java, si queremos usar el modo iterador, solo necesitamos dejar que nuestra clase de contenedor autodefinida implemente java.util.Iterablee implemente el método iterator() para devolver una java.util.Iteratorclase de implementación de .

Supongo que te gusta

Origin blog.csdn.net/weixin_53407527/article/details/128628099
Recomendado
Clasificación