迭代器模式

简介

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

使用场景:

  • Java集合框架(Iterator)

  • 数据库结果集(ResultSet)

  • 文件系统遍历

  • 树形结构遍历

实现要点:

  • 统一的遍历接口

  • 隐藏内部结构

  • 支持多种遍历方式

UML

代码示例

  1. 迭代器的元素,菜品菜单

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;
    }
    
    @Override
    public String toString() {
        return String.format("%-20s ¥%.2f%s\n    %s", 
                           name, price, 
                           vegetarian ? " (素)" : "", 
                           description);
    }
}
  1. 迭代器接口

public interface Iterator<T> {
    
    /**
     * 是否有下一个元素
     */
    boolean hasNext();
    
    /**
     * 获取下一个元素
     */
    T next();
    
    /**
     * 移除当前元素(可选操作)
     */
    default void remove() {
        throw new UnsupportedOperationException("不支持移除操作");
    }
}
  1. 聚合接口,包含:迭代器的创建、添加元素。

public interface Aggregate<T> {
    
    /**
     * 创建迭代器
     */
    Iterator<T> createIterator();
    
    /**
     * 添加元素
     */
    void add(T item);
    
    /**
     * 获取元素数量
     */
    int size();
}
  1. 具体实现

//早餐菜单 - 使用ArrayList存储
public class BreakfastMenu implements Aggregate<MenuItem> {
    
    private List<MenuItem> menuItems;
    
    public BreakfastMenu() {
        menuItems = new ArrayList<>();
        
        // 初始化早餐菜单
        add(new MenuItem("素食早餐", "吐司配水煮蛋", true, 15.00));
        add(new MenuItem("传统早餐", "油条豆浆", true, 8.00));
        add(new MenuItem("西式早餐", "培根煎蛋三明治", false, 25.00));
        add(new MenuItem("养生粥", "小米南瓜粥", true, 12.00));
    }
    
    @Override
    public void add(MenuItem item) {
        menuItems.add(item);
    }
    
    @Override
    public Iterator<MenuItem> createIterator() {
        return new BreakfastMenuIterator();
    }
    
    @Override
    public int size() {
        return menuItems.size();
    }
    
    /**
     * 早餐菜单迭代器 - 使用List索引遍历
     */
    private class BreakfastMenuIterator implements Iterator<MenuItem> {
        private int position = 0;
        
        @Override
        public boolean hasNext() {
            return position < menuItems.size();
        }
        
        @Override
        public MenuItem next() {
            MenuItem item = menuItems.get(position);
            position++;
            return item;
        }
    }
}
//午餐菜单 - 使用数组存储
public class LunchMenu implements Aggregate<MenuItem> {
    
    private static final int MAX_ITEMS = 6;
    private MenuItem[] menuItems;
    private int numberOfItems = 0;
    
    public LunchMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        
        // 初始化午餐菜单
        add(new MenuItem("宫保鸡丁", "经典川菜", false, 38.00));
        add(new MenuItem("鱼香肉丝", "酸辣可口", false, 35.00));
        add(new MenuItem("麻婆豆腐", "麻辣鲜香", true, 28.00));
        add(new MenuItem("红烧肉", "肥而不腻", false, 45.00));
        add(new MenuItem("清炒时蔬", "健康营养", true, 18.00));
    }
    
    @Override
    public void add(MenuItem item) {
        if (numberOfItems >= MAX_ITEMS) {
            System.err.println("菜单已满,无法添加更多菜品");
        } else {
            menuItems[numberOfItems] = item;
            numberOfItems++;
        }
    }
    
    @Override
    public Iterator<MenuItem> createIterator() {
        return new LunchMenuIterator();
    }
    
    @Override
    public int size() {
        return numberOfItems;
    }
    
    /**
     * 午餐菜单迭代器 - 使用数组索引遍历
     */
    private class LunchMenuIterator implements Iterator<MenuItem> {
        private int position = 0;
        
        @Override
        public boolean hasNext() {
            return position < numberOfItems && menuItems[position] != null;
        }
        
        @Override
        public MenuItem next() {
            MenuItem item = menuItems[position];
            position++;
            return item;
        }
    }
}
//晚餐菜单 - 使用HashMap存储
public class DinnerMenu implements Aggregate<MenuItem> {
    
    private Map<String, MenuItem> menuItems;
    
    public DinnerMenu() {
        menuItems = new HashMap<>();
        
        // 初始化晚餐菜单
        add(new MenuItem("龙虾套餐", "澳洲龙虾配黄油", false, 288.00));
        add(new MenuItem("牛排套餐", "安格斯牛排", false, 188.00));
        add(new MenuItem("海鲜大餐", "各式海鲜拼盘", false, 258.00));
        add(new MenuItem("素食套餐", "精选素食", true, 88.00));
    }
    
    @Override
    public void add(MenuItem item) {
        menuItems.put(item.getName(), item);
    }
    
    @Override
    public Iterator<MenuItem> createIterator() {
        return new DinnerMenuIterator();
    }
    
    @Override
    public int size() {
        return menuItems.size();
    }
    
    /**
     * 晚餐菜单迭代器 - 使用Map的values遍历
     */
    private class DinnerMenuIterator implements Iterator<MenuItem> {
        private java.util.Iterator<MenuItem> iterator;
        
        public DinnerMenuIterator() {
            iterator = menuItems.values().iterator();
        }
        
        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }
        
        @Override
        public MenuItem next() {
            return iterator.next();
        }
    }
}
  1. 迭代器使用者

public class Waitress {
    
    private Aggregate<MenuItem> breakfastMenu;
    private Aggregate<MenuItem> lunchMenu;
    private Aggregate<MenuItem> dinnerMenu;
    
    public Waitress(Aggregate<MenuItem> breakfastMenu, 
                   Aggregate<MenuItem> lunchMenu, 
                   Aggregate<MenuItem> dinnerMenu) {
        this.breakfastMenu = breakfastMenu;
        this.lunchMenu = lunchMenu;
        this.dinnerMenu = dinnerMenu;
    }
    
    /**
     * 打印所有菜单
     */
    public void printMenu() {
        System.out.println("📋 ========== 餐厅菜单 ==========\n");
        
        System.out.println("🌅 早餐菜单:");
        printMenu(breakfastMenu.createIterator());
        
        System.out.println("\n🌞 午餐菜单:");
        printMenu(lunchMenu.createIterator());
        
        System.out.println("\n🌙 晚餐菜单:");
        printMenu(dinnerMenu.createIterator());
    }
    
    /**
     * 打印单个菜单
     */
    private void printMenu(Iterator<MenuItem> iterator) {
        while (iterator.hasNext()) {
            MenuItem item = iterator.next();
            System.out.println("  " + item);
        }
    }
    
    /**
     * 打印素食菜单
     */
    public void printVegetarianMenu() {
        System.out.println("\n🥬 ========== 素食菜单 ==========\n");
        
        System.out.println("🌅 早餐:");
        printVegetarianMenu(breakfastMenu.createIterator());
        
        System.out.println("\n🌞 午餐:");
        printVegetarianMenu(lunchMenu.createIterator());
        
        System.out.println("\n🌙 晚餐:");
        printVegetarianMenu(dinnerMenu.createIterator());
    }
    
    /**
     * 打印素食菜单项
     */
    private void printVegetarianMenu(Iterator<MenuItem> iterator) {
        while (iterator.hasNext()) {
            MenuItem item = iterator.next();
            if (item.isVegetarian()) {
                System.out.println("  " + item);
            }
        }
    }
    
    /**
     * 检查是否有某个菜品
     */
    public boolean isItemVegetarian(String name) {
        Iterator<MenuItem> iterator = breakfastMenu.createIterator();
        if (isItemVegetarian(iterator, name)) {
            return true;
        }
        
        iterator = lunchMenu.createIterator();
        if (isItemVegetarian(iterator, name)) {
            return true;
        }
        
        iterator = dinnerMenu.createIterator();
        return isItemVegetarian(iterator, name);
    }
    
    private boolean isItemVegetarian(Iterator<MenuItem> iterator, String name) {
        while (iterator.hasNext()) {
            MenuItem item = iterator.next();
            if (item.getName().equals(name)) {
                return item.isVegetarian();
            }
        }
        return false;
    }
}
  1. 使用方式

public class Test {

    public static void main(String[] args) {
        System.out.println("=== 迭代器模式 - 餐厅菜单示例 ===\n");

        // 创建不同的菜单(使用不同的数据结构)
        Aggregate<MenuItem> breakfastMenu = new BreakfastMenu();  // 使用ArrayList
        Aggregate<MenuItem> lunchMenu = new LunchMenu();          // 使用数组
        Aggregate<MenuItem> dinnerMenu = new DinnerMenu();        // 使用HashMap

        System.out.println("📝 菜单信息:");
        System.out.println("  早餐菜单: 使用ArrayList存储,共" + breakfastMenu.size() + "道菜");
        System.out.println("  午餐菜单: 使用数组存储,共" + lunchMenu.size() + "道菜");
        System.out.println("  晚餐菜单: 使用HashMap存储,共" + dinnerMenu.size() + "道菜");

        // 创建服务员
        Waitress waitress = new Waitress(breakfastMenu, lunchMenu, dinnerMenu);

        // ========== 场景1:打印所有菜单 ==========
        System.out.println("\n【场景1:打印所有菜单】");
        System.out.println("服务员不需要知道菜单的内部实现,统一使用迭代器遍历\n");
        waitress.printMenu();

        // ========== 场景2:打印素食菜单 ==========
        System.out.println("\n\n【场景2:打印素食菜单】");
        System.out.println("通过迭代器过滤素食菜品\n");
        waitress.printVegetarianMenu();

        // ========== 场景3:查询特定菜品 ==========
        System.out.println("\n\n【场景3:查询特定菜品】");
        String[] dishesToCheck = {"麻婆豆腐", "宫保鸡丁", "清炒时蔬", "红烧肉"};
        
        for (String dish : dishesToCheck) {
            boolean isVeg = waitress.isItemVegetarian(dish);
            System.out.println("  \"" + dish + "\" 是素食? " + (isVeg ? "✅ 是" : "❌ 否"));
        }

        // ========== 场景4:演示迭代器的独立性 ==========
        System.out.println("\n\n【场景4:演示迭代器的独立性】");
        System.out.println("可以同时创建多个迭代器,互不影响\n");
        
        Iterator<MenuItem> iterator1 = breakfastMenu.createIterator();
        Iterator<MenuItem> iterator2 = breakfastMenu.createIterator();
        
        System.out.println("迭代器1遍历早餐菜单:");
        int count1 = 0;
        while (iterator1.hasNext()) {
            MenuItem item = iterator1.next();
            count1++;
            System.out.println("  " + count1 + ". " + item.getName());
        }
        
        System.out.println("\n迭代器2独立遍历早餐菜单:");
        int count2 = 0;
        while (iterator2.hasNext()) {
            MenuItem item = iterator2.next();
            count2++;
            System.out.println("  " + count2 + ". " + item.getName());
        }

        // ========== 对比不使用迭代器 ==========
        System.out.println("\n\n【对比:不使用迭代器模式】");
        System.out.println("\n❌ 不使用迭代器:");
        System.out.println("  - 需要知道每个菜单的内部实现(ArrayList、数组、HashMap)");
        System.out.println("  - 遍历代码不统一,需要针对每种数据结构编写不同代码");
        System.out.println("  - 代码耦合度高,难以维护和扩展");
        
        System.out.println("\n✅ 使用迭代器:");
        System.out.println("  - 统一的遍历接口,不需要知道内部实现");
        System.out.println("  - 遍历代码统一,易于维护");
        System.out.println("  - 低耦合,可以轻松添加新的菜单类型");

        // ========== 总结 ==========
        System.out.println("\n\n=== 迭代器模式说明 ===");
        System.out.println("1. 迭代器接口: Iterator - 定义遍历方法");
        System.out.println("2. 聚合接口: Aggregate - 定义创建迭代器的方法");
        System.out.println("3. 具体聚合: BreakfastMenu等 - 实现具体的数据结构");
        System.out.println("4. 具体迭代器: 内部类 - 实现具体的遍历逻辑");
        System.out.println("5. 客户端: Waitress - 使用迭代器统一遍历");

        System.out.println("\n=== 迭代器模式优势 ===");
        System.out.println("✅ 统一接口: 提供统一的遍历方式");
        System.out.println("✅ 封装性: 隐藏聚合对象的内部结构");
        System.out.println("✅ 单一职责: 遍历逻辑与数据结构分离");
        System.out.println("✅ 多种遍历: 可以为同一聚合提供多种遍历方式");
        System.out.println("✅ 简化聚合接口: 聚合对象不需要提供遍历方法");

        System.out.println("\n=== 迭代器模式应用场景 ===");
        System.out.println("📌 集合遍历: Java集合框架的Iterator");
        System.out.println("📌 树形结构: 遍历树、图等复杂结构");
        System.out.println("📌 分页查询: 数据库结果集的遍历");
        System.out.println("📌 文件系统: 遍历文件和目录");
        System.out.println("📌 网络数据: 流式数据的遍历");

        System.out.println("\n=== Java中的迭代器模式 ===");
        System.out.println("🔸 java.util.Iterator: Java标准迭代器接口");
        System.out.println("🔸 java.util.Iterable: 可迭代接口");
        System.out.println("🔸 for-each循环: 基于迭代器实现");
        System.out.println("🔸 Stream API: 增强的迭代器");
        System.out.println("🔸 ResultSet: JDBC结果集迭代器");

        System.out.println("\n=== 迭代器模式关键点 ===");
        System.out.println("🔑 分离遍历行为: 将遍历逻辑从聚合对象中分离");
        System.out.println("🔑 统一接口: 所有迭代器实现相同接口");
        System.out.println("🔑 内部迭代器: 通常作为聚合对象的内部类");
        System.out.println("🔑 多游标: 可以同时存在多个迭代器");
    }
}

Last updated

Was this helpful?