Java设计模式----迭代器模式
为什么要使用这种设计模式呢?这种设计模式可以提高程序的可复用性,相比for循环更加的灵活,不管集合类怎么改变,只要集合的iterator方法能正确地返回Iterator实例,即使不对while循环做任何修改,也可以正常使用。
这里有一个小建议:不要只使用具体的类来编程,要优先使用抽象类和接口来编程。
下面上代码,为了方便理解,使用书与书架的关系编写代码
1.1 创建集合接口
/**
* 定义返回类型为Iterator的方法
* @author PeiYP
* @date 2022年01月14日 23:16
*/
public interface Aggregate {
public abstract Iterator iterator();
}
1.2 创建迭代器接口
/**
* 迭代器接口,定义了抽象方法hasNext(),next()
* @author PeiYP
* @date 2022年01月14日 23:17
*/
public interface Iterator {
/**
* 用于判断集合中是否还有下一个元素
* @author PeiYP
* @date 2022/1/14 23:53
* @return boolean 如果有返回true,如果没有返回false
*/
public abstract boolean hasNext();
/**
* 用于返回集合中的元素
* @author PeiYP
* @date 2022/1/14 23:54
* @return java.lang.Object
*/
public abstract Object next();
}
1.3 定义Book类,提供构造器和get方法
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
1.4 BookShelf 类主要存放书本信息,扮演集合的角色
常规数组写法放在注释里
public class BookShelf implements Aggregate{
//定义ArrayList类型的集合存放书籍
private ArrayList<Book> books;
/**
* 构造器用于初始化一个ArrayList数组
* @author PeiYP
* @date 2022/1/15 0:03
* @return null
*/
public BookShelf() {
this.books = new ArrayList();
}
/**
* 根据下标来获取书本信息
* 如果使用常规的数组写法,则返回 return books[index]
* @author PeiYP
* @date 2022/1/15 0:04
* @param index 下标
* @return edu.pyp.iterator.Book
*/
public Book getBookAt(int index){
return books.get(index);
}
/**
* 添加书籍
* 如果使用常规的数组写法,
* 则在外部定义一个 int 类型的last变量来记录集合的最后一个元素的下标
* 再将书籍添加到这个位置,最后 last++
* 写法:this.books[last] = book;
* last++;
* @author PeiYP
* @date 2022/1/15 0:06
* @param book
*/
public void appendBook(Book book){
this.books.add(book);
}
/**
* 获取集合长度
* 如果使用常规的数组写法,则返回 last
* @author PeiYP
* @date 2022/1/15 0:10
* @return int
*/
public int getLength(){
return books.size();
}
/**
* 重写了接口的方法 返回了一个 BookShelfIterator的实例,
* 并把集合传入BookShelfIterator的构造器中
* @author PeiYP
* @date 2022/1/15 0:11
* @return edu.pyp.iterator.Iterator
*/
@Override
public Iterator iterator() {
return new BookShelfIterator(this);
}
}
1.5 创建BookShelfIterator类,实现Iterator接口
这就是一个自定义的迭代器
/**
* 扮演迭代器的角色
* 类中定义两个属性为BookShelf类型的对象和记录下标的index
* @author PeiYP
* @date 2022年01月14日 23:26
*/
public class BookShelfIterator implements Iterator {
private BookShelf bookShelf;
private int index;
/**
* 构造器用于初始化,接收BookShelf传来的实例
* @author PeiYP
* @date 2022/1/15 0:15
* @param bookShelf 传入bookShelf对象
* @return null
*/
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
/**
* 重写接口方法,判断如果index<集合的长度,就说明还有下一条数据
* 否则就没有下一条
* @author PeiYP
* @date 2022/1/15 0:15
* @return boolean
*/
@Override
public boolean hasNext() {
if (index < bookShelf.getLength()) {
return true;
} else {
return false;
}
}
/**
* 重写接口方法,用于接收书本信息
* 内部index自增
* @author PeiYP
* @date 2022/1/15 0:17
* @return java.lang.Object
*/
@Override
public Object next() {
Book book = bookShelf.getBookAt(index);
index++;
return book;
}
}
1.6 测试代码
public class RunMain {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
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"));
bookShelf.appendBook(new Book("Daddy-Long-Legs"));
bookShelf.appendBook(new Book("Daddy-Long-Legs"));
Iterator iterator = bookShelf.iterator();
while (iterator.hasNext()) {
Book next = (Book) iterator.next();
System.out.println(next.getName());
}
}
}
在测试代码中我们可以看出,不用普通数组的原因是普通数组的数据不能重复,从而可扩展性不强。如果是多线程则建议使用Vector或其他线程安全的集合类。