Java设计模式之迭代器模式

一、简介
在使用Java进行开发时,我们通常会使用循环的方式对容器中的元素进行遍历,例如我们要去遍历一个数组中的无素,我们往往会使用for循环对数组中的元素进行遍历,因为这种方式进行取元素进行分析非常的简单,但是有些时候当数据采用hash表存储元素时,则采用迭代器模式进行存取则会方便一些。其次,迭代器模式的另一个好处就是将遍历与实现进行分离,用户无需知道数据以何种集合方式进行存储,只要获得对应的iterator迭代器实例就可以将集合中的元素取出,也就是说当管理个体的集合方式发生改变的时候,具体迭代器部份的代码也无需修改,从而达到了尽可能地复用代码的效果。
二、iterator迭代器模式类图类图
Java设计模式之迭代器模式
角色介绍:
Iterator(迭代器):定义按顺序逐个遍历元素的接口,一般情况下具有两个方法:hasNext()方法与next()方法。其中,hasNext()用于判断是否有下一无素。next()方法用于返回当前的元素并并指向下一个元素。
Concretelterator(具体迭代器):负责实现Iterator角色所定义的接口,包含遍历集合所需要的信息,其信息一般包括(1)要遍历集合的对象,知道它才能知道具体如何进行遍历;(2)遍历集合元素的下标。
Aggregate(集合):所要遍历的集合的接口。
ConcreteAggregate(具体集合):Aggregate类的具体实现。
三、例子
3.1 问题
将书(Book)放置在书架(BookShelf)中,并将书的名字按顺序显示出来。
3.2 代码
3.2.1 定义书本类(Book)

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;
    }
}


3.2.2 定义抽像(集合接口+迭代器拉口):使得实现方式多样化,降低耦合度
(1)集合接口

public interface Aggregate {
Iterator iterator();
}

(2)迭代器接口

public interface Iterator {
    boolean hasnext();//判断是否有下一个
    Object next();//取出当前个体并下移至下一个要遍历的个体
}

3.2.3 定义抽像接口的具体实现类(集合的具体实现+迭代器的具体实现)
(1)集合的具体实现

public class BookShelf implements Aggregate {
    private Book[] books;//这里用静态数组的形式进行存储个体
    private  int last=0;//在将个体添加到集合对象中时记录其添加的个数或长度

    public BookShelf(int maxSize) {
        this.books = new Book[maxSize];//申请数据空间
    }
     //添加书目
    public void appendBooks(Book book){
        this.books[last]=book;
        this.last+=1;
    }
    //拿取书目
    public Book getBook(int index){
       return this.books[index];
    }
    //获取书架上书的数目
    public int getLength(){
        return this.last;
    }
    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}

(2)迭代器的具体实现

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(this.index<bookShelf.getLength())
            return true;
        else
        return false;
    }
//进行迭代取出
    @Override
    public Object next() {
        Book book =bookShelf.getBook(index);//根据提供的下标将书取出
        index++;
        return book;
    }
}

3.2.4 测试代码

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(5);//生成书架
        //将5本书放置到书架上
        bookShelf.appendBooks(new Book("西游记"));
        bookShelf.appendBooks(new Book("东游记"));
        bookShelf.appendBooks(new Book("红楼梦"));
        bookShelf.appendBooks(new Book("三国演义"));
        bookShelf.appendBooks(new Book("算法导论"));
        Iterator iterator=bookShelf.iterator();
        //对书架上的书进行读取并显示
        while (iterator.hasnext()){
            Book book =(Book) iterator.next();
            System.out.println("此本书的书名为:"+book.getName());
        }
    }
}

3.3 程序运行结果
Java设计模式之迭代器模式

四、适用场景
迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。
但是,由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了。