设计模式-迭代器模式

写在前面

Hello,我是易元,这篇文章是我学习设计模式时的笔记和心得体会。如果其中有错误,欢迎大家留言指正!

案例

假设有一个Book类和一个管理书籍的BookCollection类,我们需要遍历BookCollection类中所有书籍信息。

一、传统实现:直接硬编码遍历逻辑

1. 基础代码

直接在集合类中添加遍历方法

图书类
复制代码
public class Book {  
    private String title;  
    private String author;  
    private int publishYear;  

    public Book() {}  

    public Book(String title, String author, int publishYear) {  
        this.title = title;  
        this.author = author;  
        this.publishYear = publishYear;  
    }  

    // Getter 和 Setter 方法  
    public String getTitle() { return title; }  
    public void setTitle(String title) { this.title = title; }  

    public String getAuthor() { return author; }  
    public void setAuthor(String author) { this.author = author; }  

    public int getPublishYear() { return publishYear; }  
    public void setPublishYear(int publishYear) { this.publishYear = publishYear; }  

    @Override  
    public String toString() {  
        return "Book{" +  
                "title='" + title + '\'' +  
                ", author='" + author + '\'' +  
                ", publishYear=" + publishYear +  
                '}';  
    }  
}  
图书集合类
复制代码
public class BookCollection {  
    private List<Book> books;  

    public BookCollection() {}  

    public BookCollection(List<Book> books) {  
        this.books = books;  
    }  

    public void printBooks() {  
        for (Book book : books) {  
            System.out.println(book.toString());  
        }  
    }  
}  
测试代码
复制代码
@Test  
public void printBookTest() {  
    List<Book> books = new ArrayList<>();  
    books.add(new Book("Java编程思想", "Bruce Eckel", 2018));  
    books.add(new Book("设计模式", "Erich Gamma", 1994));  
    books.add(new Book("鸟哥的Linux私房菜", "鸟哥", 2010));  

    BookCollection bookCollection = new BookCollection(books);  
    bookCollection.printBooks();  
}  

3. 存在的缺陷

以上述代码为例,若需要新的遍历方式(如按作者或出版年份遍历),一种方法是直接在BookCollection中添加新方法。这会破坏原有代码,每次新增遍历方式都需要修改BookCollection类。

二、设计模式实现

1. 迭代器模式

迭代器模式提供了一种遍历集合对象元素的方式,而无需暴露其内部表示。它定义了访问集合元素的接口,支持遍历不同的集合结构。

er

  • 主要角色
    • Iterator(迭代器):定义访问和遍历集合元素的接口。

    • ConcreteIterator(具体迭代器):实现迭代器接口,用于遍历集合。

    • Aggregate(集合):定义创建迭代器的接口。

    • ConcreteAggregate(具体集合):实现集合接口,返回具体迭代器实例。

2. 使用设计模式对已实现的功能进行重构

迭代器接口
复制代码
public interface BookIterator {  
    boolean hasNext();  
    Book getNext();  
}  
  • 定义标准化遍历协议:

    • hasNext():检查是否存在下一个元素

    • getNext():获取当前元素并后移指针

  • 解耦集合结构与遍历逻辑的入口

具体迭代器
复制代码
public class BookCollectionIterator implements BookIterator {  
    private List<Book> books;  
    private int position = 0;  

    public BookCollectionIterator(List<Book> books) {  
        this.books = books;  
    }  

    @Override  
    public boolean hasNext() {  
        return position < books.size();  
    }  

    @Override  
    public Book getNext() {  
        if (hasNext()) {  
            return books.get(position++);  
        }  
        return null;  
    }  
}  
  • 通过position索引跟踪遍历进度

  • 集合数据通过构造函数注入,保证迭代器独立性

集合接口
复制代码
public interface BookAggregate {  
    BookIterator createIterator();  
}  
具体集合
复制代码
public class BookCollection implements BookAggregate {  
    private List<Book> books;  

    public BookCollection(List<Book> books) {  
        this.books = books;  
    }  

    @Override  
    public BookIterator createIterator() {  
        return new BookCollectionIterator(books);  
    }  
}  
  • 通过createIterator()统一创建迭代器,隐藏实现细节

  • 新增迭代器无需修改集合类,只需扩展新实现

测试代码
复制代码
@Test  
public void test_book_def() {  
    List<Book> books = new ArrayList<>();  
    books.add(new Book("Java编程思想", "Bruce Eckel", 2018));  
    books.add(new Book("Effective Java", "Joshua Bloch", 2018));  
    books.add(new Book("设计模式", "Erich Gamma", 1994));  
    books.add(new Book("鸟哥的Linux私房菜", "鸟哥", 2010));  

    BookAggregate bookCollection = new BookCollection(books);  
    BookIterator bookIterator = bookCollection.createIterator();  

    while (bookIterator.hasNext()) {  
        Book book = bookIterator.getNext();  
        System.out.println(book.toString());  
    }  
}  
输出结果
复制代码
Book{title='Java编程思想', author='Bruce Eckel', publishYear=2018}  
Book{title='Effective Java', author='Joshua Bloch', publishYear=2018}  
Book{title='设计模式', author='Erich Gamma', publishYear=1994}  
Book{title='鸟哥的Linux私房菜', author='鸟哥', publishYear=2010}  

3. 增加按照出版年份进行遍历

新增具体集合类
复制代码
// 按年份过滤的集合  
public class BookYearAggregate implements BookAggregate {  
    private List<Book> books;  
    private int targetYear;  

    public BookYearAggregate(List<Book> books, int targetYear) {  
        this.books = books;  
        this.targetYear = targetYear;  
    }  

    @Override  
    public BookIterator createIterator() {  
        return new YearBookIterator(books, targetYear);  
    }  
}  
新增具体迭代器
复制代码
// 按出版年份过滤的迭代器  
public class YearBookIterator implements BookIterator {  
    private List<Book> books;  
    private int targetYear;  
    private int position = 0;  

    public YearBookIterator(List<Book> books, int year) {  
        this.books = books;  
        this.targetYear = year;  
    }  

    @Override  
    public boolean hasNext() {  
        // 跳过不符合年份的书籍  
        while (position < books.size()) {  
            if (books.get(position).getPublishYear() == targetYear) {  
                return true;  
            }  
            position++;  
        }  
        return false;  
    }  

    @Override  
    public Book getNext() {  
        if (hasNext()) {  
            return books.get(position++);  
        }  
        return null;  
    }  
}  
  • 按条件过滤 :在hasNext()中循环查找匹配年份,跳过非目标项

  • 独立职责:遍历逻辑与集合类完全解耦,符合单一职责原则

测试代码
复制代码
@Test  
public void test_book_year() {  
    List<Book> books = new ArrayList<>();  
    books.add(new Book("Java编程思想", "Bruce Eckel", 2018));  
    books.add(new Book("Effective Java", "Joshua Bloch", 2018));  
    books.add(new Book("设计模式", "Erich Gamma", 1994));  
    books.add(new Book("鸟哥的Linux私房菜", "鸟哥", 2010));  

    BookAggregate bookCollection = new BookYearAggregate(books, 2018);  
    BookIterator bookIterator = bookCollection.createIterator();  

    while (bookIterator.hasNext()) {  
        Book book = bookIterator.getNext();  
        System.out.println(book.toString());  
    }  
}  
输出结果
复制代码
Book{title='Java编程思想', author='Bruce Eckel', publishYear=2018}  
Book{title='Effective Java', author='Joshua Bloch', publishYear=2018}  

长话短说

迭代器模式的优势

  1. 解耦遍历逻辑

    集合类不再关心"如何遍历",只需提供数据。

  2. 支持多种遍历方式

    新增迭代器即可实现新逻辑,符合开闭原则。

  3. 简化集合接口

    集合类只需提供createIterator()方法,接口更清晰。

  4. 并行遍历

    可以同时创建多个迭代器,独立遍历同一集合。

何时使用迭代器模式?

  • 场景特征
    • 需要以不同方式遍历集合对象(如正序、逆序、过滤)。

    • 不想暴露集合的内部结构(如数组、链表等实现细节)。

    • 需要为集合提供统一的遍历接口。

相关推荐
菲兹园长10 分钟前
MyBatis-Plus
java·开发语言·mybatis
计算机学姐15 分钟前
基于SpringBoot的在线教育管理系统
java·vue.js·spring boot·后端·mysql·spring·mybatis
菜鸟破茧计划18 分钟前
滑动窗口:穿越数据的时光机
java·数据结构·算法
windwant28 分钟前
深入解析Http11AprProtocol:Tomcat高性能通信的底层原理
java·tomcat
Minyy1129 分钟前
“爱生活”小项目问题总结
java·数据库·spring boot·spring·maven·intellij-idea
修修修也35 分钟前
【C++】特殊类设计
开发语言·c++·特殊类·类与对象
Cloud Traveler40 分钟前
Java并发编程常见问题与陷阱解析
java·开发语言·python
Learning_foolish1 小时前
ThreadLocal
java
有梦想的攻城狮1 小时前
spring中的@Value注解详解
java·后端·spring·value注解
byte轻骑兵1 小时前
【C++重载操作符与转换】转换与继承
开发语言·c++