十五、行为型(迭代器模式)

发布于:2024-10-17 ⋅ 阅读:(10) ⋅ 点赞:(0)

迭代器模式(Iterator Pattern)

概念
迭代器模式是一种行为型设计模式,它用于提供一种顺序访问聚合对象(如集合、列表、数组)元素的方式,而无需暴露该对象的内部表示。迭代器模式将遍历行为从集合对象中分离出来,通过提供统一的接口来访问不同聚合对象中的元素。


应用场景

  1. 遍历集合对象:在系统中需要遍历不同类型的集合(如列表、栈、队列)时,迭代器模式可以提供一致的方式来遍历,而不必了解集合的内部结构。

  2. 封装集合的内部结构:迭代器隐藏了集合的具体实现细节,用户不需要关心集合的内部实现,例如数组的长度、链表的节点等,避免了直接操作集合对象。

  3. 解耦集合与算法:通过将遍历算法与集合本身分离,用户可以独立定义不同的迭代器,满足特定的遍历需求,如正序遍历、倒序遍历、跳步遍历等。


注意点

  • 并发修改问题:当集合在遍历过程中被修改(如新增或删除元素),可能会引发并发修改异常,需要特别注意在多线程场景下的使用。

  • 迭代器失效问题:一些容器在迭代时,如果容器内部结构改变(比如删除了一个元素),默认的迭代器会失效并抛出异常。

  • 内存管理:如果集合特别大且占用大量内存,使用迭代器遍历时应考虑如何管理内存,例如在遍历过程中是否需要保持所有元素在内存中。


核心要素

  1. Iterator(迭代器接口):定义访问和遍历元素的方法,例如next()hasNext()

  2. ConcreteIterator(具体迭代器):具体的迭代器实现,实现迭代器接口并维护遍历状态。

  3. Aggregate(聚合对象接口):定义创建迭代器的接口,用于返回具体的迭代器对象。

  4. ConcreteAggregate(具体聚合对象):具体的集合类,实现创建迭代器的接口,并负责存储对象。


Java代码完整示例

代码示例:简单的迭代器模式实现

import java.util.ArrayList;
import java.util.List;

// 迭代器接口
interface Iterator<T> {
    boolean hasNext();
    T next();
}

// 聚合对象接口
interface Aggregate<T> {
    Iterator<T> createIterator();
}

// 具体迭代器实现
class ConcreteIterator<T> implements Iterator<T> {
    private List<T> items;
    private int position = 0;

    public ConcreteIterator(List<T> items) {
        this.items = items;
    }

    @Override
    public boolean hasNext() {
        return position < items.size();
    }

    @Override
    public T next() {
        return items.get(position++);
    }
}

// 具体聚合对象实现
class ConcreteAggregate<T> implements Aggregate<T> {
    private List<T> items = new ArrayList<>();

    public void addItem(T item) {
        items.add(item);
    }

    @Override
    public Iterator<T> createIterator() {
        return new ConcreteIterator<>(items);
    }
}

// 客户端代码
public class IteratorPatternDemo {
    public static void main(String[] args) {
        ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
        aggregate.addItem("Item 1");
        aggregate.addItem("Item 2");
        aggregate.addItem("Item 3");

        Iterator<String> iterator = aggregate.createIterator();
        
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

输出结果

Item 1
Item 2
Item 3

各种变形用法完整示例

  1. 倒序迭代器
    有时需要反向遍历集合,这时可以通过实现倒序迭代器来实现。

    代码示例:倒序迭代器

    class ReverseIterator<T> implements Iterator<T> {
        private List<T> items;
        private int position;
    
        public ReverseIterator(List<T> items) {
            this.items = items;
            this.position = items.size() - 1;
        }
    
        @Override
        public boolean hasNext() {
            return position >= 0;
        }
    
        @Override
        public T next() {
            return items.get(position--);
        }
    }
    
    public class ReverseIteratorPatternDemo {
        public static void main(String[] args) {
            ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
            aggregate.addItem("Item 1");
            aggregate.addItem("Item 2");
            aggregate.addItem("Item 3");
    
            Iterator<String> reverseIterator = new ReverseIterator<>(aggregate.createIterator().items);
            
            while (reverseIterator.hasNext()) {
                System.out.println(reverseIterator.next());
            }
        }
    }
    

    输出结果

    Item 3
    Item 2
    Item 1
    
  2. 迭代器失效和并发修改异常
    当集合在迭代过程中发生变化时,通常会抛出ConcurrentModificationException异常,尤其在使用Java自带的集合类时需要特别注意。

    代码示例:并发修改异常

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class ConcurrentModificationDemo {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("Item 1");
            list.add("Item 2");
            list.add("Item 3");
    
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String item = iterator.next();
                System.out.println(item);
    
                // 在迭代过程中修改集合,抛出异常
                if ("Item 2".equals(item)) {
                    list.remove(item);
                }
            }
        }
    }
    

    输出结果

    Item 1
    Item 2
    Exception in thread "main" java.util.ConcurrentModificationException
    
  3. 自定义迭代器与泛型支持
    迭代器模式可以通过泛型来实现对不同类型的集合进行遍历。

    代码示例:自定义泛型迭代器

    class GenericAggregate<T> implements Aggregate<T> {
        private List<T> items = new ArrayList<>();
    
        public void addItem(T item) {
            items.add(item);
        }
    
        @Override
        public Iterator<T> createIterator() {
            return new ConcreteIterator<>(items);
        }
    }
    
    public class GenericIteratorPatternDemo {
        public static void main(String[] args) {
            GenericAggregate<Integer> intAggregate = new GenericAggregate<>();
            intAggregate.addItem(1);
            intAggregate.addItem(2);
            intAggregate.addItem(3);
    
            Iterator<Integer> intIterator = intAggregate.createIterator();
            while (intIterator.hasNext()) {
                System.out.println(intIterator.next());
            }
    
            GenericAggregate<String> stringAggregate = new GenericAggregate<>();
            stringAggregate.addItem("Item A");
            stringAggregate.addItem("Item B");
    
            Iterator<String> stringIterator = stringAggregate.createIterator();
            while (stringIterator.hasNext()) {
                System.out.println(stringIterator.next());
            }
        }
    }
    

    输出结果

    1
    2
    3
    Item A
    Item B
    
  4. 内部类实现迭代器
    Java标准库中的集合类,如ArrayList等,通常通过内部类实现自己的迭代器。

    代码示例:内部类实现迭代器

    class MyCollection<T> {
        private List<T> items = new ArrayList<>();
    
        public void addItem(T item) {
            items.add(item);
        }
    
        public Iterator<T> iterator() {
            return new MyIterator();
        }
    
        private class MyIterator implements Iterator<T> {
            private int index = 0;
    
            @Override
            public boolean hasNext() {
                return index < items.size();
            }
    
            @Override
            public T next() {
                return items.get(index++);
            }
        }
    }
    
    public class InnerClassIteratorDemo {
        public static void main(String[] args) {
            MyCollection<String> collection = new MyCollection<>();
            collection.addItem("Item X");
            collection.addItem("Item Y");
    
            Iterator<String> iterator = collection.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    }
    

    输出结果

    Item X
    Item Y
    

总结
迭代器模式通过提供统一的遍历接口,隐藏了聚合对象的内部结构,使得代码能够适应多种不同的集合类型。在实际开发中,Java标准库已经内置了大量的迭代器实现(如ListSet等),我们可以直接使用或扩展这些实现,来满足不同的需求。