23种设计模式——迭代器模式

163 阅读2分钟

前言:为什么要使用迭代器模式?什么时候使用迭代器模式?弄清楚这两个问题,就能明白什么是迭代器模式。

场景一:

遍历书架对象,将图书名按照顺序打印出来。且根据业务要求,书架一旦创建,能存放书的数量是固定的。

一般的实现方式如下


书类:

public class Book {
    private String bookName;

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

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
}

书架类:

public class BookShelf {

    private Book[] books;

    private int last =0;

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

    public Book[] getBooks() {
        return books;
    }

    public void setBooks(Book[] books) {
        this.books = books;
    }
}

实现代码:

public class Test {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);
        bookShelf.appendBook(new Book("A"));
        bookShelf.appendBook(new Book("B"));
        bookShelf.appendBook(new Book("C"));
        bookShelf.appendBook(new Book("D"));

        for (Book book : bookShelf.getBooks()) {
            System.out.println(book.getBookName());
        }
    }
}

场景变化:


业务升级,书架要求对书进行索引编号,且可以通过索引号取书。
修改代码: 书架类:

```
public class BookShelf {

    private Map<String,Book> books;

    public BookShelf() {
    }

    public Book getBookByKey(String key){
        return books.get(key);
    }
    
    public void appendBook(Book book,String key){
        books.put(key, book);
    }

    public Map<String, Book> getBooks() {
        return books;
    }

    public void setBooks(Map<String, Book> books) {
        this.books = books;
    }
}
```

循环也要做相应的修改

图片.png 假如项目里有多处这种循环,那么这些循环都要改。这里书架类和循环业务就是一个强关联的关系
那么有没有一种办法可以去掉这种强关联,使得我们即使修改书架的实现的同时无需修改业务代码?有,迭代器模式。
设计思路:
1.凡是书架这种聚合的类,都必定存在迭代遍历需求,所以它们必须有一个方法,来获取它们自身的迭代器。于是设计一个聚合接口,接口里定义一个获取迭代器的方法,聚合类必须实现这个接口。

public interface Agregate {
    public abstract Iterator iterator();
}
public class BookShelf implements Agregate {
    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 Book[] getBooks() {
        return books;
    }

    public void setBooks(Book[] books) {
        this.books = books;
    }

    @Override
    public Iterator iterator() {
        return null;//待定
    }
}

2.创建迭代器的接口以及书架的迭代器实现类

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}
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.getBooks().length){
            return true;
        }
        return false;
    }

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

书架类加上返回具体迭代器的代码。

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

遍历实现

public static void main(String[] args) {
    BookShelf bookShelf = new BookShelf(4);
    bookShelf.appendBook(new Book("A"));
    bookShelf.appendBook(new Book("B"));
    bookShelf.appendBook(new Book("C"));
    bookShelf.appendBook(new Book("D"));

    Iterator iterator = bookShelf.iterator();

    while (iterator.hasNext()){
        Book book = (Book) iterator.next();
        System.out.println(book.getBookName());
    }
}

如图:

图片.png 当我修改书架的实现的时候,只需要修改书架迭代器的代码即可,而不需要修改业务的代码。
总结:
迭代器模式就是将聚合类的遍历业务抽取出来封装成一个迭代器,用迭代器代替一般的遍历方法,从而代码进行解耦,并且提高了代码的复用性。