004-行爲型-04-迭代器模式(Iterator)

1、概述

  提供一種方法順序訪問一個聚合對象中各個元素, 而又無須暴露該對象的內部表示。java

  迭代器模式就是分離了集合對象的遍歷行爲,抽象出一個迭代器類來負責,這樣既能夠作到不暴露集合的內部結構,又可以讓外部代碼透明地訪問集合內部的數據。apache

  迭代模式使用比較少,JDK集合也提供了Iterator的具體實現,能夠直接拿來用,沒必要本身實現編程

1.一、適用場景

  一、訪問一個聚合對象的內容而無須暴露它的內部表示。設計模式

  二、須要爲聚合對象提供多種遍歷方式。數組

  三、爲遍歷不一樣的聚合結構提供一個統一的接口。mybatis

1.二、優缺點

優勢: 一、它支持以不一樣的方式遍歷一個聚合對象。 二、迭代器簡化了聚合類。 三、在同一個聚合上能夠有多個遍歷。 四、在迭代器模式中,增長新的聚合類和迭代器類都很方便,無須修改原有代碼。ide

缺點:因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。測試

1.三、類圖角色及其職責this

   

  迭代模式的角色和職責

  一、Iterator(迭代器接口)spa

  該接口必須定義實現迭代功能的最小定義方法集

  好比提供hasNext()和next()方法。

  二、ConcreteIterator(迭代器實現類)

  迭代器接口Iterator的實現類。能夠根據具體狀況加以實現。

  三、Aggregate(容器接口)

  定義基本功能以及提供相似Iterator iterator()的方法。

  四、concreteAggregate(容器實現類)

  容器接口的實現類。必須實現Iterator iterator()方法。

1.四、演進過程

1.4.一、初始化

建立一個容器中要存儲的內容Book

public class Book {
    private String id;
    private String name;
    private double price;

    public Book(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public void display() {
        System.out.println("ID=" + id + ",\tname=" + name + ",\tprice" + price);
    }
}
View Code

 

建立一個容器BookList

public class BookList {
    //容器內部仍是一個List,也能夠用數組
    private List<Book> bookList = new ArrayList<Book>();
    private int index;

    //添加書籍
    public void addBook(Book book){
        bookList.add(book);
    }

    //刪除書籍
    public void removeBook(Book book){
        int bookIndex = bookList.indexOf(book);
        bookList.remove(bookIndex);
    }

    //判斷是否有下一本書
    public boolean hasNext(){
        if(index >= bookList.size()){
            return false;
        }
        return true;
    }

    //得到下一本書
    public Book getNext(){
        return bookList.get(index++);
    }

    //獲取集合長度
    public int getSize(){
        return bookList.size();
    }

    //根據index獲取Book
    public Book getByIndex(int index){
        return bookList.get(index);
    }
}

  接下來,就是迭代容器了

方式1、(由容器本身實現順序遍歷。直接在容器類裏直接添加順序遍歷方法)

    @Test
    public void test1() {
        BookList bookList = new BookList();

        Book book1 = new Book("001","設計模式",200);
        Book book2 = new Book("002","Java核心編程",200);
        Book book3 = new Book("003","計算機組成原理",200);

        bookList.addBook(book1);
        bookList.addBook(book2);
        bookList.addBook(book3);

        while(bookList.hasNext()){
            Book book = bookList.getNext();
            book.display();
        }
    }

輸出

ID=001,    name=設計模式,    price200.0
ID=002,    name=Java核心編程,    price200.0
ID=003,    name=計算機組成原理,    price200.0

 

方式2、讓調用者本身實現遍歷。直接暴露數據細節給外部)

    @Test
    public void test2() {
        BookList bookList = new BookList();

        Book book1 = new Book("001", "設計模式", 200);
        Book book2 = new Book("002", "Java核心編程", 200);
        Book book3 = new Book("003", "計算機組成原理", 200);

        bookList.addBook(book1);
        bookList.addBook(book2);
        bookList.addBook(book3);

        for (int i = 0; i < bookList.getSize(); i++) {
            Book book = bookList.getByIndex(i);
            book.display();
        }
    }

結果同上

不使用迭代模式的缺點

  以上方法1與方法2均可以實現對遍歷,但有這些問題

  1,容器類承擔了太多功能:一方面須要提供添加刪除等自己應有的功能;一方面還須要提供遍歷訪問功能。

  2,每每容器在實現遍歷的過程當中,須要保存遍歷狀態,當跟元素的添加刪除等功能夾雜在一塊兒,很容易引發混亂和程序運行錯誤等。

應用迭代模式的條件

  Iterator模式就是爲了有效地處理按順序進行遍歷訪問的一種設計模式,簡單地說,Iterator模式提供一種有效的方法,能夠屏蔽彙集對象集合的容器類的實現細節,而能對容器內包含的對象元素按順序進行有效的遍歷訪問。

  因此,Iterator模式的應用場景能夠概括爲知足如下幾個條件:

  一、訪問容器中包含的內部對象
  二、按順序訪問

1.4.二、進化

用代碼實現一下迭代模式,只需修改BookList便可,BookListIterator

public class BookListIterator {
    //容器內部仍是一個List,也能夠用數組
    private List<Book> bookList = new ArrayList<Book>();
    private int index;

    //添加書籍
    public void addBook(Book book){
        bookList.add(book);
    }

    //刪除書籍
    public void removeBook(Book book){
        int bookIndex = bookList.indexOf(book);
        bookList.remove(bookIndex);
    }

    //獲取集合長度
    public int getSize(){
        return bookList.size();
    }

    //根據index獲取Book
    public Book getByIndex(int index){
        return bookList.get(index);
    }

    //獲得Iterator實例
    public Iterator Iterator() {
        return new Itr();
    }

    //內部類,Iterator實例(由於要使用容器的內部信息,因此要寫成內部類)
    private class Itr implements Iterator{
        //判斷是否有下一本書,將剛纔hasNext()中內容複製過來便可
        public boolean hasNext() {
            if(index >= bookList.size()){
                return false;
            }
            return true;
        }
        //得到下一本書,將剛纔getNext()中內容複製過來便可
        public Object next() {
            return bookList.get(index++);
        }

        public void remove() {

        }
    }
}

測試

    @Test
    public void test3() {
        BookListIterator bookList = new BookListIterator();

        Book book1 = new Book("001","設計模式",200);
        Book book2 = new Book("002","Java核心編程",200);
        Book book3 = new Book("003","計算機組成原理",200);

        bookList.addBook(book1);
        bookList.addBook(book2);
        bookList.addBook(book3);

        Iterator iterator = bookList.Iterator();
        while(iterator.hasNext()){
            Book book = (Book) iterator.next();
            book.display();
        }
    }

輸出同上

  能夠看到,這和使用JDK提供集合的Iterator方法就如出一轍了。

2、擴展

2.1 JDK

java.util.Iterator
java.util.ArrayList中的Itr

2.2 Mybatis

org.apache.ibatis.cursor.defaults.DefaultCursor的cursorIterator

 

 

 

c

相關文章
相關標籤/搜索