迭代器模式 (Iterator Pattern)

迭代器模式 (Iterator Pattern)

概述

迭代器模式是一种行为型设计模式,它提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

意图

  • 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示

适用场景

  • 访问一个聚合对象的内容而无须暴露它的内部表示
  • 需要为聚合对象提供多种遍历方式
  • 为遍历不同的聚合结构提供统一的接口

结构

复制代码
┌─────────────┐          ┌─────────────┐
│   Client    │──────────>│  Iterator   │
├─────────────┤          ├─────────────┤
│             │          │ + first()   │
└─────────────┘          │ + next()    │
                         │ + isDone()  │
                         │ + currentItem() │
                         └─────────────┘
                                 ▲
                                 │
┌─────────────┐          ┌─────────────┐
│ Aggregate   │<─────────│ConcreteIterator│
├─────────────┤          ├─────────────┤
│ + createIterator()│    │ - aggregate │
└─────────────┘          │ + first()   │
                         │ + next()    │
                         │ + isDone()  │
                         │ + currentItem() │
                         └─────────────┘
                                 ▲
                                 │
                         ┌─────────────┐
                         │ConcreteAggregate│
                         ├─────────────┤
                         │ + createIterator()│
                         └─────────────┘

参与者

  • Iterator:迭代器定义访问和遍历元素的接口
  • ConcreteIterator:具体迭代器实现迭代器接口,并跟踪聚合对象中的当前位置
  • Aggregate:聚合定义创建相应迭代器对象的接口
  • ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例

示例代码

下面是一个完整的迭代器模式示例,以自定义集合为例:

java 复制代码
import java.util.ArrayList;
import java.util.List;

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

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

// ConcreteAggregate - 具体聚合类
public class ConcreteAggregate<T> implements Aggregate<T> {
    private List<T> items = new ArrayList<>();
    
    public void add(T item) {
        items.add(item);
    }
    
    public T get(int index) {
        return items.get(index);
    }
    
    public int size() {
        return items.size();
    }
    
    @Override
    public Iterator<T> createIterator() {
        return new ConcreteIterator(this);
    }
}

// ConcreteIterator - 具体迭代器
public class ConcreteIterator<T> implements Iterator<T> {
    private ConcreteAggregate<T> aggregate;
    private int current = 0;
    
    public ConcreteIterator(ConcreteAggregate<T> aggregate) {
        this.aggregate = aggregate;
    }
    
    @Override
    public boolean hasNext() {
        return current < aggregate.size();
    }
    
    @Override
    public T next() {
        if (hasNext()) {
            return aggregate.get(current++);
        }
        return null;
    }
    
    @Override
    public void reset() {
        current = 0;
    }
}

// Client - 客户端
public class Client {
    public static void main(String[] args) {
        // 创建聚合对象
        ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
        aggregate.add("元素1");
        aggregate.add("元素2");
        aggregate.add("元素3");
        aggregate.add("元素4");
        aggregate.add("元素5");
        
        // 创建迭代器
        Iterator<String> iterator = aggregate.createIterator();
        
        // 使用迭代器遍历聚合对象
        System.out.println("第一次遍历:");
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println(item);
        }
        
        // 重置迭代器
        iterator.reset();
        
        System.out.println("\n重置后第二次遍历:");
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println(item);
        }
    }
}

另一个示例 - 反向迭代器

java 复制代码
// ReverseIterator - 反向迭代器
public class ReverseIterator<T> implements Iterator<T> {
    private ConcreteAggregate<T> aggregate;
    private int current;
    
    public ReverseIterator(ConcreteAggregate<T> aggregate) {
        this.aggregate = aggregate;
        this.current = aggregate.size() - 1;
    }
    
    @Override
    public boolean hasNext() {
        return current >= 0;
    }
    
    @Override
    public T next() {
        if (hasNext()) {
            return aggregate.get(current--);
        }
        return null;
    }
    
    @Override
    public void reset() {
        current = aggregate.size() - 1;
    }
}

// Client - 客户端
public class Client {
    public static void main(String[] args) {
        // 创建聚合对象
        ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
        aggregate.add("元素1");
        aggregate.add("元素2");
        aggregate.add("元素3");
        aggregate.add("元素4");
        aggregate.add("元素5");
        
        // 创建正向迭代器
        Iterator<String> forwardIterator = aggregate.createIterator();
        
        System.out.println("正向遍历:");
        while (forwardIterator.hasNext()) {
            String item = forwardIterator.next();
            System.out.println(item);
        }
        
        // 创建反向迭代器
        Iterator<String> reverseIterator = new ReverseIterator<>(aggregate);
        
        System.out.println("\n反向遍历:");
        while (reverseIterator.hasNext()) {
            String item = reverseIterator.next();
            System.out.println(item);
        }
    }
}

Java中的迭代器模式

Java中的集合框架广泛使用了迭代器模式:

java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JavaIteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        list.add("JavaScript");
        
        // 使用迭代器遍历
        System.out.println("使用迭代器遍历:");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String language = iterator.next();
            System.out.println(language);
        }
        
        // 使用增强for循环遍历(底层也是迭代器)
        System.out.println("\n使用增强for循环遍历:");
        for (String language : list) {
            System.out.println(language);
        }
        
        // 使用Java 8的forEach方法
        System.out.println("\n使用forEach方法遍历:");
        list.forEach(System.out::println);
    }
}

自定义迭代器实现

下面是一个更复杂的自定义迭代器实现,以菜单系统为例:

java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

// MenuItem - 菜单项
public class MenuItem {
    private String name;
    private String description;
    private boolean vegetarian;
    private double price;
    
    public MenuItem(String name, String description, boolean vegetarian, double price) {
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    
    public String getName() {
        return name;
    }
    
    public String getDescription() {
        return description;
    }
    
    public boolean isVegetarian() {
        return vegetarian;
    }
    
    public double getPrice() {
        return price;
    }
}

// MenuComponent - 菜单组件抽象类
public abstract class MenuComponent {
    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }
    
    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }
    
    public MenuComponent getChild(int i) {
        throw new UnsupportedOperationException();
    }
    
    public String getName() {
        throw new UnsupportedOperationException();
    }
    
    public String getDescription() {
        throw new UnsupportedOperationException();
    }
    
    public boolean isVegetarian() {
        throw new UnsupportedOperationException();
    }
    
    public double getPrice() {
        throw new UnsupportedOperationException();
    }
    
    public abstract Iterator<MenuComponent> createIterator();
    public abstract void print();
}

// MenuItem - 菜单项实现
public class MenuItem extends MenuComponent {
    private String name;
    private String description;
    private boolean vegetarian;
    private double price;
    
    public MenuItem(String name, String description, boolean vegetarian, double price) {
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public String getDescription() {
        return description;
    }
    
    @Override
    public boolean isVegetarian() {
        return vegetarian;
    }
    
    @Override
    public double getPrice() {
        return price;
    }
    
    @Override
    public Iterator<MenuComponent> createIterator() {
        return new NullIterator();
    }
    
    @Override
    public void print() {
        System.out.print("  " + getName());
        if (isVegetarian()) {
            System.out.print("(v)");
        }
        System.out.println(", " + getPrice());
        System.out.println("     -- " + getDescription());
    }
}

// Menu - 菜单实现
public class Menu extends MenuComponent {
    private List<MenuComponent> menuComponents = new ArrayList<>();
    private String name;
    private String description;
    
    public Menu(String name, String description) {
        this.name = name;
        this.description = description;
    }
    
    @Override
    public void add(MenuComponent menuComponent) {
        menuComponents.add(menuComponent);
    }
    
    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponents.remove(menuComponent);
    }
    
    @Override
    public MenuComponent getChild(int i) {
        return menuComponents.get(i);
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public String getDescription() {
        return description;
    }
    
    @Override
    public Iterator<MenuComponent> createIterator() {
        return new CompositeIterator(menuComponents.iterator());
    }
    
    @Override
    public void print() {
        System.out.print("\n" + getName());
        System.out.println(", " + getDescription());
        System.out.println("---------------------");
        
        Iterator<MenuComponent> iterator = menuComponents.iterator();
        while (iterator.hasNext()) {
            MenuComponent menuComponent = iterator.next();
            menuComponent.print();
        }
    }
}

// NullIterator - 空迭代器
public class NullIterator implements Iterator<MenuComponent> {
    @Override
    public boolean hasNext() {
        return false;
    }
    
    @Override
    public MenuComponent next() {
        return null;
    }
    
    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

// CompositeIterator - 组合迭代器
public class CompositeIterator implements Iterator<MenuComponent> {
    private Stack<Iterator<MenuComponent>> stack = new Stack<>();
    
    public CompositeIterator(Iterator<MenuComponent> iterator) {
        stack.push(iterator);
    }
    
    @Override
    public boolean hasNext() {
        if (stack.empty()) {
            return false;
        } else {
            Iterator<MenuComponent> iterator = stack.peek();
            if (!iterator.hasNext()) {
                stack.pop();
                return hasNext();
            } else {
                return true;
            }
        }
    }
    
    @Override
    public MenuComponent next() {
        if (hasNext()) {
            Iterator<MenuComponent> iterator = stack.peek();
            MenuComponent component = iterator.next();
            if (component instanceof Menu) {
                stack.push(component.createIterator());
            }
            return component;
        } else {
            return null;
        }
    }
    
    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

// Waitress - 服务员
public class Waitress {
    private MenuComponent allMenus;
    
    public Waitress(MenuComponent allMenus) {
        this.allMenus = allMenus;
    }
    
    public void printMenu() {
        allMenus.print();
    }
    
    public void printVegetarianMenu() {
        Iterator<MenuComponent> iterator = allMenus.createIterator();
        System.out.println("\nVEGETARIAN MENU\n----");
        while (iterator.hasNext()) {
            MenuComponent menuComponent = iterator.next();
            try {
                if (menuComponent.isVegetarian()) {
                    menuComponent.print();
                }
            } catch (UnsupportedOperationException e) {
                // 不处理
            }
        }
    }
}

// Client - 客户端
public class Client {
    public static void main(String[] args) {
        // 创建所有菜单
        MenuComponent allMenus = new Menu("所有菜单", "所有菜单组合");
        
        // 创建早餐菜单
        MenuComponent breakfastMenu = new Menu("早餐菜单", "早餐菜单");
        breakfastMenu.add(new MenuItem("煎饼", "煎饼配豆浆", true, 3.99));
        breakfastMenu.add(new MenuItem("包子", "肉包子", false, 2.99));
        
        // 创建午餐菜单
        MenuComponent lunchMenu = new Menu("午餐菜单", "午餐菜单");
        lunchMenu.add(new MenuItem("汉堡", "牛肉汉堡", false, 8.99));
        lunchMenu.add(new MenuItem("沙拉", "蔬菜沙拉", true, 5.99));
        
        // 创建晚餐菜单
        MenuComponent dinnerMenu = new Menu("晚餐菜单", "晚餐菜单");
        dinnerMenu.add(new MenuItem("牛排", "烤牛排", false, 15.99));
        dinnerMenu.add(new MenuItem("意大利面", "素食意大利面", true, 12.99));
        
        // 创建甜点菜单
        MenuComponent dessertMenu = new Menu("甜点菜单", "甜点菜单");
        dessertMenu.add(new MenuItem("蛋糕", "巧克力蛋糕", true, 4.99));
        dessertMenu.add(new MenuItem("冰淇淋", "香草冰淇淋", true, 3.99));
        
        // 将甜点菜单添加到晚餐菜单中
        dinnerMenu.add(dessertMenu);
        
        // 将所有菜单添加到总菜单中
        allMenus.add(breakfastMenu);
        allMenus.add(lunchMenu);
        allMenus.add(dinnerMenu);
        
        // 创建服务员
        Waitress waitress = new Waitress(allMenus);
        
        // 打印所有菜单
        waitress.printMenu();
        
        // 打印素食菜单
        waitress.printVegetarianMenu();
    }
}

优缺点

优点

  1. 它支持以不同的方式遍历一个聚合
  2. 简化了聚合对象的接口
  3. 在同一个聚合上可以有多个遍历同时进行

缺点

  1. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性

相关模式

  • 组合模式:迭代器模式经常与组合模式一起使用,以遍历组合结构中的所有元素
  • 工厂方法模式:迭代器通常使用工厂方法模式来创建
  • 备忘录模式:迭代器模式可以使用备忘录模式来保存遍历状态

实际应用

  • Java集合框架中的Iterator接口
  • Java中的Enumeration接口
  • 数据库游标
  • 文件系统遍历
  • XML/HTML文档解析

注意事项

  1. 迭代器模式中的迭代器应该是轻量级的,不应该包含过多的状态
  2. 迭代器模式中的聚合对象不应该暴露其内部结构
  3. 迭代器模式中的迭代器应该是独立的,不依赖于聚合对象的具体实现
  4. 迭代器模式中的迭代器应该是可重用的,可以在不同的聚合对象上使用
相关推荐
小码过河.15 小时前
设计模式——迭代器模式
设计模式·迭代器模式
Engineer邓祥浩10 天前
设计模式学习(18) 23-16 迭代器模式
学习·设计模式·迭代器模式
JavaBoy_XJ1 个月前
行为型-迭代器模式
迭代器模式
__万波__1 个月前
二十三种设计模式(十六)--迭代器模式
java·设计模式·迭代器模式
Yeniden1 个月前
Deepeek用大白话讲解 --> 迭代器模式(企业级场景1,多种遍历方式2,隐藏集合结构3,Java集合框架4)
java·开发语言·迭代器模式
老朱佩琪!1 个月前
Unity迭代器模式
unity·设计模式·迭代器模式
563471002 个月前
信用风险传播机制 金融网络传播模型 感染率 初始感染比例 matlab编写代码程序 复杂网络
迭代器模式
开心香辣派小星2 个月前
23种设计模式-14迭代器模式
设计模式·迭代器模式
ZHE|张恒2 个月前
设计模式(十六)迭代器模式 — 统一访问集合元素的方式,不暴露内部结构
设计模式·迭代器模式