Iterator 迭代器模式

意图

提供了一种方法来访问一个聚合对象中的各个元素,而不需要暴露其内部的表示。

结构

在这里插入图片描述

  • 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则是具体的迭代器。客户端通过调用BookShelfcreateIterator方法获取迭代器,然后利用迭代器来遍历书架上的所有书籍。这样,即使BookShelf内部的结构发生变化(比如从ArrayList改为其他类型的集合),只要迭代器的接口不变,客户端代码就不需要修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老攀呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值