定义
迭代器模式(Iterator Pattern)是一种行为设计模式,它提供一种遍历容器对象(例如列表、集合、数组等)元素的统一接口,而无需了解底层数据结构的实现细节。
迭代器模式的主要目标是将遍历操作从容器对象中分离出来,使得可以独立地对容器进行遍历操作,同时保持容器对象的封装性。这样,我们可以通过迭代器逐个访问容器中的元素,而不必暴露容器内部的表示方式和结构。
迭代器模式的主要参与者包括:
- 迭代器(Iterator):定义了访问和遍历元素的接口,包括获取下一个元素、判断是否还有元素等方法。
- 具体迭代器(Concrete Iterator):实现了迭代器接口,负责实际遍历容器中的元素。
- 容器(Container):定义了创建迭代器的接口,可以是一个集合、列表、数组等数据结构。
- 具体容器(Concrete Container):实现了容器接口,负责创建具体迭代器对象。
迭代器模式的优点包括:
- 简化了容器的接口:迭代器模式将遍历操作抽象出来,使得容器的接口更加简洁。
- 支持多种遍历方式:通过定义不同的迭代器,可以支持不同的遍历方式,如正向遍历、逆向遍历等。
- 提供了统一的遍历接口:迭代器模式定义了统一的遍历接口,使得客户端可以一致地处理不同的容器对象。
迭代器模式常见的应用场景包括遍历数据库结果集、遍历集合类对象、文件的逐行读取等。它提供了一种灵活、可扩展的方式来遍历容器元素,同时降低了容器与迭代算法之间的耦合度。
示例一:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// 容器接口
interface Container {
Iterator<String> getIterator();
}
// 具体容器实现类
class NameContainer implements Container {
private List<String> names;
public NameContainer() {
names = new ArrayList<>();
}
public void addName(String name) {
names.add(name);
}
@Override
public Iterator<String> getIterator() {
return new NameIterator();
}
// 具体迭代器实现类
private class NameIterator implements Iterator<String> {
private int index;
@Override
public boolean hasNext() {
return index < names.size();
}
@Override
public String next() {
if (hasNext()) {
return names.get(index++);
}
return null;
}
}
}
// 客户端代码
public class IteratorPatternExample {
public static void main(String[] args) {
NameContainer container = new NameContainer();
container.addName("John");
container.addName("Jane");
container.addName("David");
Iterator<String> iterator = container.getIterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println("Name: " + name);
}
}
}
在上面的示例中,我们定义了一个容器接口Container,包含一个getIterator()方法用于获取迭代器对象。然后我们实现了具体的容器类NameContainer,其中使用内部类NameIterator来实现迭代器接口Iterator。
在客户端代码中,我们创建了一个NameContainer对象,并向容器中添加了几个名字。然后通过调用getIterator()方法获取迭代器对象,并使用while循环遍历容器中的元素并打印出来。
通过迭代器模式,我们将遍历容器的操作从容器对象中分离出来,使得容器和遍历逻辑可以独立变化。这样,我们可以通过修改迭代器实现类来改变遍历方式,而不必修改容器类的代码。
示例二:遍历一个购物车中的商品列表
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// 商品类
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;
}
}
// 购物车类
class ShoppingCart implements Iterable<Product> {
private List<Product> products;
public ShoppingCart() {
products = new ArrayList<>();
}
public void addProduct(Product product) {
products.add(product);
}
@Override
public Iterator<Product> iterator() {
return new ProductIterator();
}
// 商品迭代器
private class ProductIterator implements Iterator<Product> {
private int index;
@Override
public boolean hasNext() {
return index < products.size();
}
@Override
public Product next() {
if (hasNext()) {
return products.get(index++);
}
return null;
}
}
}
// 客户端代码
public class IteratorPatternExample {
public static void main(String[] args) {
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.addProduct(new Product("Apple", 2.5));
shoppingCart.addProduct(new Product("Banana", 1.5));
shoppingCart.addProduct(new Product("Orange", 3.0));
double totalPrice = 0.0;
for (Product product : shoppingCart) {
System.out.println("Product: " + product.getName() + ", Price: $" + product.getPrice());
totalPrice += product.getPrice();
}
System.out.println("Total Price: $" + totalPrice);
}
}
在上面的示例中,我们定义了一个商品类Product,具有名称和价格属性。然后我们创建了一个购物车类ShoppingCart,其中包含一个商品列表products,可以向购物车中添加商品,并实现了Iterable接口,使其可以被遍历。
购物车类中还定义了内部类ProductIterator作为商品的迭代器,实现了Iterator接口的方法。在客户端代码中,我们创建了一个购物车对象并向其中添加了几个商品,然后使用for循环遍历购物车中的商品,并打印每个商品的名称和价格,同时计算总价。
通过迭代器模式,我们将遍历购物车中商品的操作从购物车类中分离出来,使得购物车类只关注商品的添加和管理,而不需要暴露内部的数据结构。同时,使用迭代器可以方便地遍历购物车中的商品,进行相应的操作,如计算总价等。