Iterator迭代器模式------数据集合的遍历

一、迭代器(Iterator)模式要解决的问题

使用java语言显示数组中元素时,可以使用for循环遍历数组:

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

通过数组的下标我们可以取出数组任意索引位置的值,所以通过i的不断自增,我们可以取出数组中的所有元素。将这里的循环变量i的作用抽象化、通用化后形成的模式,在设计模式中称为Iterator模式。该模式用于在数据集合中按照顺序遍历集合。

二、说明迭代器模式的示例程序

我们这里会定义一个书籍类(Book)和一个书架类(BookShelf),实现一个可以遍历书架上书籍的迭代器。
类图
迭代类图结构
类说明
类说明
类代码
1、Aggregate接口
该接口声明了一个iterator方法,该方法会生成一个用于遍历集合的迭代器。遍历集合时只要调用iterator方法生成一个实现了Iterator接口的类的实例。

package com.dsanjun.gof.iterator;
/**
 * 表示集合类接口
 * 
 * @author dyw
 * @date 2019年10月5日
 */
public interface Aggregate {
	/**
	 * 返回迭代器
	 * 
	 * @return 迭代器
	 */
	public abstract Iterator iterator();
}

2、Iterator 接口
简单的Iterator接口包含两个方法,hasNext用于判断是否存在下一个元素,next用于取回下一个元素,需要注意的是next方法还需要包含将迭代器移动至下一个元素的功能。

package com.dsanjun.gof.iterator;

/**
 * 遍历集合的迭代器接口
 * 
 * @author dyw
 * @date 2019年10月5日
 */
public interface Iterator {
	/**
	 * 是否有下一个元素(用于终止循环)
	 * 
	 * @return
	 */
	public abstract boolean hasNext();

	/**
	 * 返回下一个元素
	 * 
	 * @return
	 */
	public abstract Object next();
}

3、Book类

package com.dsanjun.gof.iterator;

/**
 * 书籍类
 * 
 * @author dyw
 * @date 2019年10月5日
 */
public class Book {
	private String name;

	public Book(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Book [name=" + name + "]";
	}
}

4、BookShelf类
该类实现了Aggregate接口的iterator方法,返回一个用于迭代BookShelf的Iterator实现类的一个实例。

package com.dsanjun.gof.iterator;

/**
 * 书架类
 * 
 * @author dyw
 * @date 2019年10月5日
 */
public class BookShelf implements Aggregate {
	/** 书的数组 */
	private Book[] books;
	/** 实际元素数量 */
	private int size = 0;

	/**
	 * 初始化一个数组
	 * 
	 * @param maxsize 数组最大长度
	 */
	public BookShelf(int maxsize) {
		this.books = new Book[maxsize];
	}

	/**
	 * 获取指定索引位置的元素,这个方法会在迭代器中使用
	 * 
	 * @param index 索引位置
	 * @return Book 书籍对象
	 */
	public Book getBookAt(int index) {
		return books[index];
	}

	/**
	 * 往数组末位添加元素
	 * 
	 * @param Book 书籍对象
	 */
	public void appendBook(Book book) {
		this.books[size] = book;
	}

	/**
	 * 获取元素个数(模拟集合的size),这个方法会在迭代器中使用
	 * 
	 * @return 元素个数
	 */
	public int size() {
		return size;
	}

	@Override
	public Iterator iterator() {
		return new BookShelfIterator(this);
	}

}

5、BookShelfIterator类
该类适用于迭代BookShelf,由于需要发挥迭代功能,所以要实现Iterator接口的方法。构造函数初始化一个BookShelf实例保存到bookShelf域中,并将index初始化为0。hasNext用于判断是否还有下一个元素,next方法返回当前迭代所指向的书籍,并将迭代器指向下一本书。

package com.dsanjun.gof.iterator;

/**
 * 书架对象的迭代器
 * 
 * @author dyw
 * @date 2019年10月5日
 */
public class BookShelfIterator implements Iterator {
	/** 书架对象 */
	private BookShelf bookShelf;
	/** 当前迭代器指针位置 */
	private int index;

	public BookShelfIterator(BookShelf bookShelf) {
		this.bookShelf = bookShelf;// 注入迭代对象
		this.index = 0;// 初始化指针位置
	}

	@Override
	public boolean hasNext() {
		if (index < bookShelf.size()) {
			return true;
		} else {
			return false;
		}
	}

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

6、测试主程序

package com.dsanjun.gof.iterator;

public class Main {
	public static void main(String[] args) {
		BookShelf bookShelf = new BookShelf(4);
		bookShelf.appendBook(new Book("Around the World in 80 Days"));
		bookShelf.appendBook(new Book("Bible"));
		bookShelf.appendBook(new Book("Cinderella"));
		bookShelf.appendBook(new Book("Daddy-Long-Legs"));
		Iterator it = bookShelf.iterator();
		while (it.hasNext()) {
			Book book = (Book) it.next();
			System.out.println(book.getName());
		}
	}
}

三、Iterator 模式中的一些重要角色

Iterator模式类图
Iterator模式类图
Iterator 模式中各个类的作用
在这里插入图片描述

四、Iterator 模式中的思路拓展

1、为什么要引入Iterator 这种复杂的设计模式?请看以下代码:

while(it.hasNext()){
  Book book =(Book)it.next();
  System.out.println(book.getName());
} 

这里我们只是使用了Iterator接口的hasNext和next方法,并没有调用BookShelf的方法。也就是说,这里的while循环并不依赖于BookShelf的实现。如果开发人员决定放弃使用数组来管理书籍,而是用java.util.Vector替代,会怎样?不管BookShelf如何变化,只要BookShelf的iterator方法能够正确的返回Iterator 实例,即使不对上面的while循环做任何修改,代码都能正常工作。所谓“可复用”,就是指将类实现为“组件”,当一个组件发生变化时,不需要对其他的组件进行修改或是需要很小的修改即可应对。
2、使用接口编程可以弱化类之间的耦合,进而使得类更加容易作为组件被再次利用。
3、注意迭代器和持有迭代器的类是一一对应的,比如BookShelfIterator和BookShelf就是对应的关系,因为在BookShelfIterator中调用了BookShelf的方法。

五、Iterator 模式中的注意事项Iterator 模式中的注意事项

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

豢龙先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值