第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 中如何应用?
如何为组合模式实现访问者模式?