意图
提供了一种方法来访问一个聚合对象中的各个元素,而不需要暴露其内部的表示。
结构
- Iterator(迭代器) 定义访问和遍历元素的接口。
- ConcreteIterator(具体迭代器) 实现迭代器接口;对该聚合遍历时跟踪当前位置。
- Aggregate(聚合)定义创建相应迭代器对象的接口。
- ConcreteAggregate(具体聚合) 实现创建相应迭代器的接口,该操作返回Concretelterator的一个适当的实例。
适用性
Iterator 模式适用于:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 支持对聚合对象的多种遍历。
- 为遍历不同的聚合结构提供一个统一的接口。
实例
展示商品列表
假设我们正在开发一个在线购物平台,该平台需要展示商品列表给用户。为了简化问题,我们考虑一个商品列表页面,其中包含不同类别的商品,比如电子产品、图书、服装等。每个类别都可以看作是一个聚合对象,我们可以使用迭代器模式来遍历这些商品。
场景描述
- 我们有一个
ProductCollection
类,代表商品集合。 - 每个商品由
Product
类表示。 - 我们希望提供一种方法让用户可以按顺序浏览某个类别的所有商品,而不需要知道这个类别的具体实现细节。
代码实现
1. 定义迭代器接口
public interface Iterator {
boolean hasNext();
Product next();
}
2. 定义聚合接口
public interface Aggregate {
Iterator createIterator();
}
3. 实现具体的聚合类ProductCollection
import java.util.ArrayList;
import java.util.List;
public class ProductCollection implements Aggregate {
private List<Product> products = new ArrayList<>();
public void addProduct(Product product) {
this.products.add(product);
}
@Override
public Iterator createIterator() {
return new ProductIterator(this);
}
// 提供访问内部列表的方法,仅供迭代器使用
List<Product> getProducts() {
return this.products;
}
}
4. 实现具体的迭代器ProductIterator
public class ProductIterator implements Iterator {
private ProductCollection collection;
private int index = 0;
public ProductIterator(ProductCollection collection) {
this.collection = collection;
}
@Override
public boolean hasNext() {
return index < collection.getProducts().size();
}
@Override
public Product next() {
if (this.hasNext()) {
return collection.getProducts().get(index++);
} else {
return null; // 或者抛出异常
}
}
}
5. 商品类Product
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return "Product: " + name + ", Price: " + price;
}
}
6. 使用示例
public class Main {
public static void main(String[] args) {
ProductCollection electronics = new ProductCollection();
electronics.addProduct(new Product("Smartphone", 799.99));
electronics.addProduct(new Product("Laptop", 1299.99));
electronics.addProduct(new Product("Tablet", 499.99));
Iterator iterator = electronics.createIterator();
while (iterator.hasNext()) {
Product product = iterator.next();
System.out.println(product.toString());
}
}
}
解释
在这个例子中,ProductCollection
充当了聚合的角色,它包含多个Product
对象。ProductIterator
是具体的迭代器,它实现了Iterator
接口,并且能够遍历ProductCollection
中的产品。通过这种方式,客户端代码(例如商品列表页面)可以通过调用createIterator()
方法获取迭代器,然后使用迭代器来逐个访问商品,而不必关心ProductCollection
的具体实现细节。
这种设计使得系统更加灵活和可扩展,例如如果将来需要改变商品的存储方式或添加新的遍历逻辑,只需要修改迭代器部分即可,不会影响到客户端代码。
遍历书架
这里我们将使用一个BookShelf
作为聚合对象,它包含多个Book
对象。然后,我们为这个书架创建一个迭代器,允许用户遍历书架上的书籍。
首先定义Iterator
接口:
public interface Iterator {
boolean hasNext();
Object next();
}
接着是Aggregate
接口:
public interface Aggregate {
Iterator createIterator();
}
现在,我们实现具体的聚合类BookShelf
,它将存储Book
对象,并提供创建迭代器的方法:
import java.util.ArrayList;
import java.util.List;
public class BookShelf implements Aggregate {
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
this.books.add(book);
}
@Override
public Iterator createIterator() {
return new BookShelfIterator(this);
}
// 允许访问内部列表,仅供迭代器使用
List<Book> getBooks() {
return this.books;
}
}
接下来是具体迭代器的实现BookShelfIterator
,它实现了Iterator
接口:
public class BookShelfIterator implements Iterator {
private BookShelf bookShelf;
private int index = 0;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return index < bookShelf.getBooks().size();
}
@Override
public Object next() {
if (this.hasNext()) {
return bookShelf.getBooks().get(index++);
} else {
return null; // 或者抛出异常
}
}
}
最后是Book
类,以及如何使用这些类的示例代码:
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
bookShelf.addBook(new Book("Design Patterns"));
bookShelf.addBook(new Book("Clean Code"));
bookShelf.addBook(new Book("Refactoring"));
Iterator iterator = bookShelf.createIterator();
while (iterator.hasNext()) {
Book book = (Book) iterator.next();
System.out.println("Reading: " + book.getName());
}
}
}
在这个例子中,BookShelf
扮演了聚合的角色,而BookShelfIterator
则是具体的迭代器。客户端通过调用BookShelf
的createIterator
方法获取迭代器,然后利用迭代器来遍历书架上的所有书籍。这样,即使BookShelf
内部的结构发生变化(比如从ArrayList
改为其他类型的集合),只要迭代器的接口不变,客户端代码就不需要修改。