设计模式:Iterator模式

Iterator模式用于在数据集合中按照顺序遍历集合.英语单词Iterate有反复做某件事情的意思,汉语称为"迭代器"

示例程序
这段程序是将书(Book)放置到书架(BookShelf)中,并将书名字按顺序显示出来.

Aggregate接口
Aggregate接口是所要遍历的集合的接口.实现了该接口的类就将称为一个可以保存多个元素的集合,就像数组一样.Aggregate有"使聚集"的意思

Iterator设计模式示例UML图
示例程序UML图
类和接口一览表
类和接口一览表
Aggregate接口(Aggregate.java)

public interface Aggregate {
    public abstract Iterator iterator();
}

接下来看看Iterator接口.Iterator接口用于遍历集合中的元素,其作用相当于循环语句中的循环变量.
Iterator接口(Iterator.java)

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}
这里声明了连个方法,既判断是否存在下一个元素的hasNext方法,和获取下一个元素的next方法.
hasNext方法的返回值是boolean类型的,原因很容易理解.当集合中存在下一个元素时,该方法返回true;当集合不存在下一个元素时(已经遍历至集合末尾时),该方法返回false.hasNext方法主要用于循环终止条件.
说明一下next方法.该方法的返回类型是object,这表明返回的是集合中的一个元素.但是,next方法的作用并非仅仅如此.为了能够在下次调用next方法时正确地返回下一个元素,该方法中还隐藏着迭代器移动至下一个元素的处理.说"隐含",是因为Iterator接口只知道方法名.想要知道next方法中到底进行了什么样的处理,还需要看一下实现了Iterator接口的类(BookShelfIterator).这样,我们才能看懂next方法的作用.

Book类
Book类是表示书的类.但是这个类的作用有限,它可以做的事情只有一件——通过getName方法获取书的名字.书的名字是在外部调用Book类的构造函数并初始化Book类时,作为参数传递给Book类的.
Book类(Book.java)

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

    public String getName(){
        return name;
    }
}

BookShelf类
BookShelf类是表示书架的类.由于要将该类作为集合进行处理,因此它实现了Aggregate接口.代码中的implements Aggregate部分即表示这一点.此外,请注意在BookShelf类中还实现了Aggregate接口的Iterator方法.

BookShelf(BookShelf.java)

public class BookShelf implements Aggregate{
    private Book[] books;
    private int last = 0;
    public BookShelf(int maxsize) {
        this.books = new Book[maxsize];
    }

    public Book getBookAt(int index){
        return books[index];
    }

    public void appendBook(Book book){
        this.books[last] = book;
        last++;
    }

    public int getLength(){
        return last;
    }

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

这个书架(BookShelf.java)中定义了books字段,它是Book类型的数组.该数组的大小(maxsize)在生成BookShelf的示例时就被指定了.之所以将books字段的可见性设置为private,是为了防止外部不小心改变了该字段的值.
接下来看看Iterator方法.该方法会生成并返回BookShelfIterator类的示例作为BookShelf类对应的Iterator.当外部想要遍历书架(BookShelf.java)时,就会调用这个方法.

BookShelfIterator类
BookShelfIterator类(BookShelfIterator.java)

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.getLength()){
            return true;
        }else {
            return false;
        }
    }

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

因为BookShelfIterator类需要发挥Iterator的作用,所以他实现了Iterator接口.
BookShelf字段表示BookShelfIterator所要遍历的书架.index字段表示迭代器当前所指向的书的下标.
构造函数将会接收到的BookShelf的实例保存在bookShelf字段中,并将index初始化0.
hasnext方法是Iterator接口中所声明的方法.该方法将会判断书架中还有没有下一本书,如果有就返回true,没有就返回false.而要知道书架中有没有下一本书,可以通过比较index和书架总册数(bookShelf.getlength()的返回值)来判断.
next方法会返回迭代器当前所指向的书(Book的实例),并让迭代器指向下一本书.它也是Iterator接口中所声明的方法.next方法稍微有些复杂,它首先取出book变量作为返回值,然后让index指向后面一本书.

Main类
Main类(main.java)

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("Bibe"));
        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());
        }

    }
}

通过BookShelf.Iterator()得到的it是用于遍历书架的Iterator实例.while部分的条件当然是it.hasNext()了.只要书架(BookShelf.java)有书,while循环就不会停止.然后,程序会通过it.next()一本一本地遍历书架中的书.

运行结果:


Around the World in 80 Days
Bibe
Cinderella
Daddy-Long-Legs

Process finished with exit code 0

Iterator模式中的各个角色
Iterator(迭代器)
该角色负责定义按顺序逐个遍历元素的接口(API).在示例程序中,由Iterator接口扮演这个角色,它定义了hasnext和next两个方法.其中,hasNext方法用于判断是否存在下一个元素,next方法则用于获取该元素.

ConcreteIterator(具体的迭代器)
该角色负责实现Iterator角色所定义的接口(API).这个接口(API)是一个方法,会创建出"按顺序访问保存在我内部元素的人".在示例程序中,由Aggregate接口扮演这个角色,它里面定义了Iterator方法.

Aggregate(集合)
该角色负责定义创建Iterator角色的接口(API).这个接口(API)是一个方法,会创建出"按顺序访问保存在我内部元素的人".案例中,由Aggregate接口扮演这个角色,它里面定义了Iterator方法.

ConcreteAggregate(具体的集合)
该角色负责实现Aggregate角色所定义的接口(API).它会创建出具体的Iterator角色,即ConcreteIterator角色.示例程序中,由BookShelf扮演这个角色,它实现了Iterator方法.

Iterator模式的类图在这里插入图片描述
思路要点
为什么一定要考虑引入Iterator这种设计模式?如果是数组,直接使用for循环句进行遍历处理不就可以了吗?为什么要在集合之外引入Iterator这个角色呢?
一个重要的理由是,引入Iterator后可以 将遍历与实现分离开来.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值