迭代器模式(十九)

相信自己,请一定要相信自己

上一章简单介绍了访问者模式(十八), 如果没有看过, 请观看上一章

一. 迭代器模式

引用 菜鸟教程里面迭代器模式介绍: https://www.runoob.com/design-pattern/iterator-pattern.html

迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。

这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

迭代器模式属于行为型模式。

一.一 介绍

意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。

主要解决: 不同的方式来遍历整个整合对象。

何时使用: 遍历一个聚合对象。

如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。

关键代码: 定义接口:hasNext, next。

应用实例: JAVA 中的 iterator。

优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点: 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。

注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。


组成角色 具体 关系
Iterator MyIterator 迭代器接口,是系统提供,含义 hasNext, next, remove
ConcreteIterator BookShelfIterator,BookShelfReverseIterator 具体的迭代器类,管理迭代
Aggregate Aggregate 一个统一的聚合接口, 将客户端和具体聚合解耦
ConcreteAggreage BookShelf 具体的聚合持有对象集合, 并提供一个方法,返回一个迭代器, 该迭代器可以正确遍历 集合

image-20230615174455088

二. 迭代器实例

二.一 迭代的实体对象 Book

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Serializable {
    
    
    private String name;
    private String author;
}

二.二 迭代器接口 MyIterator

可以直接使用 java 提供的 java.util.Iterator 接口

public interface MyIterator<T> {
    
    
    public boolean hasNext();

    public T next() ;

}

二.三 聚合接口 Aggregate

定义了两个迭代器

public interface Aggregate<T> {
    
    

    /**
     定义不同的迭代器
     */

    public MyIterator<T> getInterator();

    public MyIterator<T> getReverseInterator();


}

二.四 迭代器实现 BookShelfIterator

二.四.一 正序迭代器

public class BookShelfIterator implements MyIterator<Book>{
    
    
    private BookShelf bookShelf;

    private int index = 0;

    public BookShelfIterator(BookShelf bookShelf) {
    
    
        this.bookShelf = bookShelf;
    }
    @Override
    public boolean hasNext() {
    
    
        return bookShelf.getLength() > index;
    }

    @Override
    public Book next() {
    
    
        Book bookAt = bookShelf.getBookAt(index);
        index++;
        return bookAt;
    }

}

二.四.二 倒序迭代器

public class BookShelfReverseIterator implements MyIterator<Book>{
    
    
    private BookShelf bookShelf;

    private int index = -1;

    public BookShelfReverseIterator(BookShelf bookShelf) {
    
    
        this.bookShelf = bookShelf;
        this.index = bookShelf.getLength()-1;
    }
    @Override
    public boolean hasNext() {
    
    
        return index >= 0;
    }

    @Override
    public Book next() {
    
    
        Book bookAt = bookShelf.getBookAt(index);
        index--;
        return bookAt;
    }

}

二.五 具体聚合接口 BookShelf

public class BookShelf implements Aggregate<Book>{
    
    
    private List<Book> bookList = new ArrayList<>();

    @Override
    public MyIterator<Book> getInterator() {
    
    
        return new BookShelfIterator(this);
    }

    @Override
    public MyIterator<Book> getReverseInterator() {
    
    
        return new BookShelfReverseIterator(this);
    }

    public Integer getLength() {
    
    
        return bookList.size();
    }

    public void appendBook(Book book) {
    
    
        this.bookList.add(book);
    }
    public Book getBookAt(Integer position) {
    
    
        return this.bookList.get(position);
    }
}

二.六 客户端调用

@Test
    public void oneTest() {
    
    
        BookShelf bookShelf = new BookShelf();
        bookShelf.appendBook(new Book("第一本书","第一本书"));
        bookShelf.appendBook(new Book("第二本书","第二本书"));
        bookShelf.appendBook(new Book("第三本书","第三本书"));
        bookShelf.appendBook(new Book("第四本书","第四本书"));
        bookShelf.appendBook(new Book("第五本书","第五本书"));

        MyIterator<Book> interator = bookShelf.getInterator();
        while (interator.hasNext()) {
    
    
            Book book = interator.next();
            log.info("打印信息: {}", book);
        }

        // 打印反转的信息.
        log.info(">>>> 倒序的信息");

        MyIterator<Book> reverseInterator = bookShelf.getReverseInterator();
        while (reverseInterator.hasNext()) {
    
    
            Book book = reverseInterator.next();
            log.info("打印信息: {}", book);
        }
    }

image-20230615175210079

在 Java 中 集合迭代的话,是很方便的

正序迭代:

@Test
    public void twoTest() {
    
    
        List<Book> bookList = new ArrayList<>();
        bookList.add(new Book("第一本书","第一本书"));
        bookList.add(new Book("第二本书","第二本书"));
        bookList.add(new Book("第三本书","第三本书"));
        bookList.add(new Book("第四本书","第四本书"));
        bookList.add(new Book("第五本书","第五本书"));


        Iterator<Book> iterator = bookList.iterator();
        while (iterator.hasNext()) {
    
    
            Book book = iterator.next();
            log.info("打印信息: {}", book);
        }

    }

image-20230615175317809

优点

  1. 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。

  2. 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。

  3. 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。

在聚合类中,我们把 迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。 而如果遍历方式改变的话,只影响到了迭代器。
4) 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式

缺点

  1. 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类

本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Iterator


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

猜你喜欢

转载自blog.csdn.net/yjltx1234csdn/article/details/131233215