迭代器模式(Iterator)
意图
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
UML 图
优点
- 简化访问接口:提供统一的遍历接口,简化客户端代码
- 封装内部结构:隐藏聚合对象的内部表示,提高安全性
- 支持多种遍历:可以在同一聚合上实现多种遍历方式
- 开闭原则:增加新的聚合类和迭代器类都很方便,无需修改现有代码
- 并行遍历:支持对同一聚合同时进行多个遍历
缺点
- 增加系统复杂度:需要定义额外的迭代器类,增加类的数量
- 性能开销:对于简单的聚合,使用迭代器可能比直接遍历效率低
- 可能破坏封装:某些迭代器实现可能需要访问聚合的内部细节
- 使用限制:某些语言(如Java)的迭代器是单向的,不能回退或重置
- 并发问题:在遍历过程中修改聚合可能导致并发异常
代码示例
以人类社交网络中的朋友关系为例:
1. 迭代器接口 (Iterator Interface)
// 迭代器接口
public interface FriendIterator {boolean hasNext();Person next();void reset();
}
2. 聚合接口 (Aggregate Interface)
// 聚合接口
public interface SocialNetwork {FriendIterator createIterator(String type);void addFriend(Person person);void removeFriend(Person person);
}
3. 具体聚合类 (Concrete Aggregate)
// 人类社交网络
public class HumanSocialNetwork implements SocialNetwork {private List<Person> friends = new ArrayList<>();private Map<String, List<Person>> friendsByCategory = new HashMap<>();@Overridepublic FriendIterator createIterator(String type) {switch (type) {case "close":return new CloseFriendsIterator(friends);case "recent":return new RecentFriendsIterator(friends);case "byInterest":return new InterestBasedIterator(friendsByCategory);default:return new AllFriendsIterator(friends);}}@Overridepublic void addFriend(Person person) {friends.add(person);// 按兴趣分类for (String interest : person.getInterests()) {friendsByCategory.computeIfAbsent(interest, k -> new ArrayList<>()).add(person);}}@Overridepublic void removeFriend(Person person) {friends.remove(person);// 从所有分类中移除for (List<Person> categoryFriends : friendsByCategory.values()) {categoryFriends.remove(person);}}public List<Person> getFriends() {return new ArrayList<>(friends); // 返回副本保护内部数据}
}
4. 具体迭代器实现 (Concrete Iterators)
// 所有朋友迭代器
public class AllFriendsIterator implements FriendIterator {private List<Person> friends;private int position;public AllFriendsIterator(List<Person> friends) {this.friends = new ArrayList<>(friends); // 保护性拷贝this.position = 0;}@Overridepublic boolean hasNext() {return position < friends.size();}@Overridepublic Person next() {if (!hasNext()) {throw new NoSuchElementException("没有更多朋友了");}return friends.get(position++);}@Overridepublic void reset() {position = 0;}
}// 亲密朋友迭代器(基于亲密程度)
public class CloseFriendsIterator implements FriendIterator {private List<Person> closeFriends;private int position;public CloseFriendsIterator(List<Person> allFriends) {this.closeFriends = allFriends.stream().filter(friend -> friend.getCloseness() >= 8) // 亲密程度8分以上.sorted((f1, f2) -> Integer.compare(f2.getCloseness(), f1.getCloseness())).collect(Collectors.toList());this.position = 0;}@Overridepublic boolean hasNext() {return position < closeFriends.size();}@Overridepublic Person next() {return closeFriends.get(position++);}@Overridepublic void reset() {position = 0;}
}// 最近添加的朋友迭代器
public class RecentFriendsIterator implements FriendIterator {private List<Person> recentFriends;private int position;public RecentFriendsIterator(List<Person> allFriends) {this.recentFriends = allFriends.stream().sorted((f1, f2) -> f2.getAddedDate().compareTo(f1.getAddedDate())).limit(10) // 最近10个朋友.collect(Collectors.toList());this.position = 0;}@Overridepublic boolean hasNext() {return position < recentFriends.size();}@Overridepublic Person next() {return recentFriends.get(position++);}@Overridepublic void reset() {position = 0;}
}// 基于兴趣的迭代器
public class InterestBasedIterator implements FriendIterator {private Map<String, List<Person>> friendsByCategory;private Iterator<Map.Entry<String, List<Person>>> categoryIterator;private Iterator<Person> currentCategoryIterator;public InterestBasedIterator(Map<String, List<Person>> friendsByCategory) {this.friendsByCategory = new HashMap<>(friendsByCategory);this.categoryIterator = this.friendsByCategory.entrySet().iterator();this.currentCategoryIterator = Collections.emptyIterator();}@Overridepublic boolean hasNext() {while (!currentCategoryIterator.hasNext() && categoryIterator.hasNext()) {Map.Entry<String, List<Person>> entry = categoryIterator.next();currentCategoryIterator = entry.getValue().iterator();}return currentCategoryIterator.hasNext();}@Overridepublic Person next() {if (!hasNext()) {throw new NoSuchElementException("没有更多朋友了");}return currentCategoryIterator.next();}@Overridepublic void reset() {categoryIterator = friendsByCategory.entrySet().iterator();currentCategoryIterator = Collections.emptyIterator();}
}
5. 人类实体类 (Person Entity)
// 人类实体
public class Person {private String name;private int closeness; // 亲密程度 1-10private LocalDate addedDate;private Set<String> interests;public Person(String name, int closeness, Set<String> interests) {this.name = name;this.closeness = closeness;this.addedDate = LocalDate.now();this.interests = new HashSet<>(interests);}// Getter方法public String getName() { return name; }public int getCloseness() { return closeness; }public LocalDate getAddedDate() { return addedDate; }public Set<String> getInterests() { return new HashSet<>(interests); }@Overridepublic String toString() {return name + " (亲密程度: " + closeness + ", 兴趣: " + interests + ")";}
}
6. 客户端代码
public class IteratorPatternDemo {public static void main(String[] args) {System.out.println("=== 迭代器模式演示 - 人类社交网络 ===\n");// 创建社交网络SocialNetwork socialNetwork = new HumanSocialNetwork();// 添加朋友socialNetwork.addFriend(new Person("张三", 9, Set.of("音乐", "运动")));socialNetwork.addFriend(new Person("李四", 7, Set.of("读书", "旅游")));socialNetwork.addFriend(new Person("王五", 10, Set.of("运动", "美食")));socialNetwork.addFriend(new Person("赵六", 6, Set.of("电影", "游戏")));socialNetwork.addFriend(new Person("钱七", 8, Set.of("音乐", "艺术")));System.out.println("1. 遍历所有朋友:");FriendIterator allIterator = socialNetwork.createIterator("all");while (allIterator.hasNext()) {System.out.println(" 👥 " + allIterator.next());}System.out.println("\n2. 遍历亲密朋友 (亲密程度≥8):");FriendIterator closeIterator = socialNetwork.createIterator("close");while (closeIterator.hasNext()) {System.out.println(" ❤️ " + closeIterator.next());}System.out.println("\n3. 按兴趣分类遍历朋友:");FriendIterator interestIterator = socialNetwork.createIterator("byInterest");while (interestIterator.hasNext()) {System.out.println(" 🎯 " + interestIterator.next());}System.out.println("\n4. 重置迭代器并重新遍历:");closeIterator.reset();while (closeIterator.hasNext()) {System.out.println(" 🔄 " + closeIterator.next());}// 演示多种遍历方式同时进行System.out.println("\n5. 同时进行多种遍历:");FriendIterator iterator1 = socialNetwork.createIterator("all");FriendIterator iterator2 = socialNetwork.createIterator("close");System.out.println(" 所有朋友中的第一个: " + iterator1.next());System.out.println(" 亲密朋友中的第一个: " + iterator2.next());System.out.println(" 所有朋友中的第二个: " + iterator1.next());}
}
在Java标准库中的应用
迭代器模式在Java标准库中的广泛应用:
- Collection框架
// Java集合框架中的迭代器
List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> iterator = list.iterator(); // 创建迭代器while (iterator.hasNext()) {String element = iterator.next();System.out.println(element);
}
- Map的keySet和entrySet
// Map的迭代器使用
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);// 遍历键
Iterator<String> keyIterator = map.keySet().iterator();
while (keyIterator.hasNext()) {System.out.println(keyIterator.next());
}// 遍历键值对
Iterator<Map.Entry<String, Integer>> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {Map.Entry<String, Integer> entry = entryIterator.next();System.out.println(entry.getKey() + ": " + entry.getValue());
}
- 增强for循环(语法糖)
// 增强for循环底层使用迭代器
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) { // 编译后使用iterator()System.out.println(name);
}
- 自定义迭代器实现
// 实现Iterable接口创建自定义迭代器
public class Range implements Iterable<Integer> {private final int start;private final int end;public Range(int start, int end) {this.start = start;this.end = end;}@Overridepublic Iterator<Integer> iterator() {return new RangeIterator();}private class RangeIterator implements Iterator<Integer> {private int current = start;@Overridepublic boolean hasNext() {return current <= end;}@Overridepublic Integer next() {if (!hasNext()) throw new NoSuchElementException();return current++;}}
}// 使用自定义迭代器
Range range = new Range(1, 5);
for (int num : range) {System.out.println(num); // 输出1,2,3,4,5
}
总结
迭代器模式通过提供统一的遍历接口,使得客户端代码能够以一致的方式访问各种聚合对象的元素,而无需关心其内部结构。在人类社交网络的例子中,我们可以看到如何为不同类型的朋友关系(亲密朋友、最近朋友、按兴趣分类等)提供不同的遍历方式。
模式核心思想:将遍历逻辑从聚合对象中分离出来,封装到专门的迭代器对象中,实现遍历与聚合的分离,提高系统的灵活性和可维护性。
适用场景:
- 需要为聚合对象提供多种遍历方式时
- 需要统一遍历接口,屏蔽不同聚合的内部差异时
- 需要支持对同一聚合的并行遍历时
通过迭代器模式,我们能够以更加灵活和可控的方式处理集合元素的遍历,特别是在复杂的社交网络或数据集合处理场景中。