9Head First Design Patterns(第2版)

迭代器与组合模式

遍历与树形结构

迭代器模式组合模式统一接口遍历策略

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第9章:迭代器与组合模式(Iterator & Composite)

一、导读

1.1 本章学习目标

第9章讲解迭代器模式和组合模式——两种用于遍历和组合对象的结构型模式。

1.2 为什么第九章如此重要

迭代器提供统一的遍历接口,组合模式将对象组织成树形结构。两者在集合框架和 UI 组件中广泛应用。

1.3 核心问题引导

迭代器模式如何统一遍历接口?

组合模式如何表示树形结构?

内部迭代器和外部迭代器有什么区别?

组合模式如何处理叶子和容器?


二、核心概念详解

9.1 迭代器模式

java
// Java 内置迭代器
public interface Iterator<E> {
    boolean hasNext();
    E next();
}

public interface Iterable<E> {
    Iterator<E> iterator();
}

// 使用
List<String> list = List.of("a", "b", "c");
for (String s : list) {  // 内部使用迭代器
    System.out.println(s);
}

// 自定义迭代器
public class Menu implements Iterable<MenuItem> {
    private List<MenuItem> items = new ArrayList<>();
    
    public void addItem(MenuItem item) { items.add(item); }
    
    public Iterator<MenuItem> iterator() {
        return items.iterator();
    }
}

9.2 组合模式

java
// 组件接口
public abstract class MenuComponent {
    public abstract String getName();
    public abstract String getDescription();
    public abstract double getPrice();
    
    // 容器方法(叶子节点不支持)
    public void add(MenuComponent component) {
        throw new UnsupportedOperationException();
    }
    public void remove(MenuComponent component) {
        throw new UnsupportedOperationException();
    }
    public Iterator<MenuComponent> createIterator() {
        throw new UnsupportedOperationException();
    }
}

// 叶子节点
public class MenuItem extends MenuComponent {
    private String name;
    private String description;
    private double price;
    
    public String getName() { return name; }
    public String getDescription() { return description; }
    public double getPrice() { return price; }
}

// 容器节点
public class Menu extends MenuComponent {
    private List<MenuComponent> components = new ArrayList<>();
    private String name;
    
    public void add(MenuComponent component) { components.add(component); }
    public void remove(MenuComponent component) { components.remove(component); }
    public String getName() { return name; }
    public String getDescription() { return name; }
    public double getPrice() { return 0; }
    
    public Iterator<MenuComponent> createIterator() {
        return new CompositeIterator(components.iterator());
    }
}

9.3 统一遍历

java
// 组合迭代器:递归遍历树形结构
public class CompositeIterator implements Iterator<MenuComponent> {
    private Stack<MenuComponent> stack = new Stack<>();
    
    public CompositeIterator(Iterator<MenuComponent> iterator) {
        while (iterator.hasNext()) {
            MenuComponent component = iterator.next();
            stack.push(component);
        }
    }
    
    public boolean hasNext() { return !stack.isEmpty(); }
    
    public MenuComponent next() {
        MenuComponent component = stack.pop();
        Iterator<MenuComponent> iterator = component.createIterator();
        while (iterator.hasNext()) {
            stack.push(iterator.next());
        }
        return component;
    }
}

三、实战案例

9.1 文件系统遍历

java
// 组合模式表示文件系统
public abstract class FileSystemComponent {
    public abstract String getName();
    public abstract long getSize();
    public abstract void add(FileSystemComponent c);
    public abstract Iterator<FileSystemComponent> iterator();
}

public class File extends FileSystemComponent {
    private String name;
    private long size;
    // 叶子节点
}

public class Directory extends FileSystemComponent {
    private String name;
    private List<FileSystemComponent> children = new ArrayList<>();
    // 容器节点
}

四、本章小结

迭代器提供统一的遍历接口,组合模式将对象组织成树形结构。组合迭代器可以递归遍历树形结构。


五、思考与练习

迭代器模式的好处是什么?

组合模式如何处理叶子和容器?

内部迭代器和外部迭代器有什么区别?

组合模式在 UI 中如何应用?

如何为组合模式实现访问者模式?


9/12迭代器与
0%