设计模式之迭代器模式

一、引入

当我们使用循环遍历数组中的数据时,通常会使用如下代码:

for(int i = 0; i< arr.length; i++){
  System.out.println(arr[i]);
}

此时我们可以将这个自增变量i 进行抽象化,通用化,并达到遍历效果,从而形成了一个新的设计模式,叫做迭代器模式。

二、示例程序

此处我们使用一段将书放到书架上,并把名字显示出来的代码,使用iterator模式进行演示

  1. Aggregate接口 是所要遍历的集合的借口,实现了该接口的类将成为一个可以保存多个元素的集合,就像数组一样。

    public interface Aggregate{
        // 用于生成一个用于遍历集合的迭代器
        Iterator iterator();
    }
    
  2. 接下来我们创建Iterator接口,用于遍历集合中的元素,其作用是相当于循环语句中的循环变量,此处我们只编写最简单的Iterator接口。

    public interface Iterator{
       // 判断是否存在下一个元素
       boolean hasNext();
       // 读取下一个元素
       Object next();
    }
    
  3. 创建书籍的数据传输对象 Book

    /**.
     * 创建书籍的数据传输对象
     * @param name 书籍的名称
     */
    public record Book(String name) {}
    
  4. 创建BookShelf类,该类作为集合处理,实现Aggregate 接口,用于存储书籍

    /**.
     * 实现存储书籍的效果
     */
    public class BookShelf implements Aggregate{
        
        private Book [] books;
    
        private int last = 0;
    
        public BookShelf(int maxSize){
            this.books = new Book[maxSize];
        }
    
        /**.
         *  通过索引获取书本
         * @param index 索引位置
         * @return 对象的书籍
         */
        public Book getBookAt(int index){
            return books[index];
        }
    
        /**.
         * 添加书籍到书架中
         * @param book 需要添加的书籍
         */
        public void appendBook(Book book){
            this.books[last] = book;
            last++;
        }
    
        /**.
         * 获取当前书架的容量
         * @return 数组当前的容量大小
         */
        public int getLength(){
            return last;
        }
    
    
        @Override
        public Iterator iterator() {
            return new BookShelIterator(this);
        }
    }
    
  5. 创建书架迭代类BookShelfIterator,实现迭代器方法。

    /**.
    * 用于书架中书籍的迭代
    */
    public class BookShelIterator implements Iterator {
       /**.
        * 书架对象
        */
       private BookShelf bookShelf;
    
       /**.
        * 当前索引,指向书籍的下标
        */
       private int index;
    
       /**.
        * 初始化书架,以及初始索引
        * @param bookShelf
        */
       public BookShelIterator(BookShelf bookShelf) {
           this.bookShelf = bookShelf;
           this.index = 0;
       }
    
       /**.
        * 判断是否还存在下一个元素
        * @return
        */
       @Override
       public boolean hasNext() {
           return index < bookShelf.getLength();
       }
    
       /**.
        * 返回对应元素
        * @return 返回对应的元素对象
        */
       @Override
       public Object next() {
           // 创建通过索引获取的对象
           Book bookAt = bookShelf.getBookAt(index);
           // 增加索引获取下一位
           index++;
           // 返回当前获取到的数据
           return bookAt;
       }
    }
    
  6. 此时我们的准备工作已经完成可以进行测试

    public static void main(String[] args) {
            BookShelf bookShelf = new BookShelf(3);
    
            bookShelf.appendBook(new Book("张三"));
            bookShelf.appendBook(new Book("李四"));
            bookShelf.appendBook(new Book("王五"));
    
            Iterator iterator = bookShelf.iterator();
    
            while (iterator.hasNext()) {
                Book next = (Book)iterator.next();
    
                System.out.println("next.name() = " + next.name());
            }
      }
    

    此时控制台便会输出

    next.name() = 张三
    next.name() = 李四
    next.name() = 王五
    
  7. 此时我们的测试示例使用迭代器来遍历书架中的书籍,便成功实现,通过书架迭代器获取迭代器的实例对象,只要while 条件中的hasNext()方法为true,我们便可以通过next()方法获取到书籍对象,一本本遍历出来了。

三、如何实现迭代器模式

  1. 必须包含的四个组成部分
    1. Iterator 也就是迭代器
      用于定义按顺序诸葛遍历元素的接口,在示例程序中我们使用的Iterator就是这个,它定义了两个方法,即hasNext()next(),分别用于判断是否存在下一个元素和获取该元素。
    2. ConcreteIterator也就是具体的迭代器
      用于实现迭代器中所定义的方法,就像咱们示例程序中的 BookShelfIterator,其中包含了遍历集合所需要的信息,
    3. Aggregate(集合)
      也就是我们创建迭代器所定义的接口,会创建出按照顺序访问保存在内部的元素。
    4. ConcreteAggregate(具体的集合)
      用于实现集合的接口,创建具体的迭代器ConcreteIterator,在示例程序中为BookShelf类,它实现了iterator这个方法。
  2. Iterator模式的类图
Creates
«interface»
Aggregate
iterator()
ConcreteAggregate
iterator()
«interface»
Iterator
next
hasNext()
ConcreteIterator
aggregate
hasNext()
next()

四、为什么要引入Iterator设计模式

引入Iterator模式后,可以将遍历与实现分离开来,当我们进行迭代遍历的时候,只是使用了IteratorhasNext()next()方法,并没有使用 BookShelf的方法,也就是说我们的while循环并不依赖于BookShelf的实现。

五、思考

如果书的数量超过了最初指定的容量大小,就无法继续向书架中添加书籍,请大家使用java.util.ArrayList修改程序,确保当书的容量超过最初指定的书架容量也能继续向书架中添加书本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值