設計模式-迭代器模式

1. 迭代器模式概述

迭代器模式, 我以爲這個圖仍是很貼切的. 迭代器至關因而電視機的遙控器, 聚合對象至關因而電視機. 電視機中有不少電視頻道的集合, 那些電視頻道究竟是怎麼組合在一塊兒的, 咱們並不知道, 也無需知道, 由於遙控器也就是迭代器給咱們提供了遍歷電視頻道的方法, 咱們只須要調用不一樣的迭代器方法便可遍歷電視機中全部節目的集合.java

在軟件開發中, 咱們常常須要使用聚合對象來存儲一系列的數據. 聚合對象有兩個職責: 存儲數據; 遍歷數據. 從依賴性來看, 前者是聚合對象的基本職責; 然後者既是可變的, 也是可分離的. 所以可將遍歷數據的行爲從聚合對象中分離出來, 封裝在一個被稱爲"迭代器"的對象中, 由迭代器來提供遍歷局和對象內部數據的行爲, 這將簡化聚合對象的設計, 更符合"單一職責原則"的要求.算法

迭代器模式: 提供一種方法來訪問聚合對象, 而不用暴露這個對象的內部表示, 其別名爲 遊標. 迭代器模式是一種對象行爲型模式.編程

在迭代器模式中包含聚合和迭代器兩個層次結構, 考慮到系統的靈活性和可擴展性, 在迭代器模式中應用了工廠方法模式, 模式結構圖以下:設計模式

迭代器模式中的幾個角色:app

  • 抽象迭代器(Iterator): 它定義了訪問和遍歷元素的接口, 聲明瞭用於遍歷數據元素的方法.
  • 具體迭代器(ConcreteIterator): 它實現了抽象迭代器接口, 完成對聚合對象的遍歷, 同時在具體迭代器中經過遊標來記錄在聚合對象中所處的當前位置, 在聚合實現時, 遊標一般是一個表示位置的非負整數.
  • 抽象聚合類(Aggregate): 用於存儲和管理元素對象, 聲明一個createIterator()方法, 該方法用於建立一個具體聚合類對象, 充當抽象迭代器的工廠角色.
  • 聚合聚合類(ConcreteAggregate): 它實現了在抽象聚合類中聲明的createIterator()方法, 該方法返回一個與該具體聚合類對應的聚合迭代器ConcreateIterator實例.

在迭代器模式中,提供了一個外部的迭代器來對聚合對象進行訪問和遍歷,迭代器定義了一個訪問該聚合元素的接口,而且能夠跟蹤當前遍歷的元素,瞭解哪些元素已經遍歷過而哪些沒有。迭代器的引入,將使得對一個複雜聚合對象的操做變得簡單。編程語言

2. Swift實現迭代器模式

一個簡單的迭代器模式的Swift實現ide

抽象迭代器  AbsIterator 

// 抽象迭代器, 用接口來聲明
protocol AbsIterator {
    
    func next()
    func isLast() -> Bool
    func previous()
    func isFirst() -> Bool
    func getNextItem() -> AnyObject
    func getPreviousItem() -> AnyObject
    
}

具體迭代器 ContreateIterator

class ContreateIterator: NSObject, AbsIterator {

    var productList: ProductList
    var list: [AnyObject]
    
    var cursor1: Int
    var cursor2: Int
    
    init(productList: ProductList) {
        
        self.productList = productList
        list = productList.objects
        cursor1 = 0
        cursor2 = list.count
        
    }
    
    func next() {
        cursor1 += 1
    }
    func isLast() -> Bool {
        return cursor1 == list.count
    }
    func previous() {
        cursor2 -= 1
    }
    func isFirst() -> Bool {
        return cursor2 == 0
    }
    func getNextItem() -> AnyObject {
        return list[cursor1]
    }
    func getPreviousItem() -> AnyObject {
        return list[cursor2]
    }
    
}

抽象聚合類 AbsObjectList

class AbsObjectList: NSObject {
    
    var objects: [AnyObject]
    
    init(objs: [AnyObject]) {
        
        objects = objs
        
    }
    
    func getObjects() -> [AnyObject] {
        return objects;
    }
    
    func addObject(obj: AnyObject) {
        objects.append(obj)
    }
    
    func removeObject(obj: AnyObject) {
        
    }
    
    func createIterator() -> AbsIterator {
        return Optional.none!
    }
}

具體聚合類 ProductList

class ProductList: AbsObjectList {
    
    override init(objs: [AnyObject]) {
        super.init(objs: objs)
    }
    
    override func createIterator() -> AbsIterator {
        return ContreateIterator(productList: self)
    }
}





客戶端代碼:

var array = [String]()

array.append("walden")
array.append("wei")
array.append("shengli")
array.append("liuyong")
array.append("jinlong")

let products = ProductList(objs: array as [AnyObject])

let iterator = products.createIterator()

print("\(iterator.getNextItem())")

若是在如上所示代碼中增長新的具體聚合類, 只需增長新的聚合類子類和一個新的具體迭代器類, 原有類庫代碼無需修改, 符合開閉原則; 若是須要更換迭代器, 只須要增長一個新的具體迭代器做爲抽象迭代器的子類, 從新實現遍歷方法, 符合開閉原則; 可是若是要在迭代器中增長新的方法, 則須要修改抽象迭代器源代碼, 這將違背開閉原則.工具

在迭代器模式的結構圖中, 咱們能夠看到具體迭代器類和具體聚合類之間存在雙重關係, 其中一個關係爲關聯關係, 在具體迭代器中須要維持一個隊具體聚合對象的引用, 該關聯關係的目的是訪問存儲在聚合對象中的數據, 以便迭代器可以對這些數據進行遍歷操做. 除了使用關聯關係, 爲了可以讓迭代器能夠訪問到聚合對象中的數據, 咱們能夠將迭代器設計爲聚合類的內部類, 在java的JDK中, 就是經過這種方式實現的..net

3. 總結

迭代器模式是一種使用頻率很是高的設計模式,經過引入迭代器能夠將數據的遍歷功能從聚合對象中分離出來,聚合對象只負責存儲數據,而遍歷數據由迭代器來完成。因爲不少編程語言的類庫都已經實現了迭代器模式,所以在實際開發中,咱們只須要直接使用Java、C#等語言已定義好的迭代器便可,迭代器已經成爲咱們操做聚合對象的基本工具之一。設計

3.1 主要優勢

迭代器模式的主要優勢以下:

  1. 它支持以不一樣的方式遍歷一個聚合對象,在同一個聚合對象上能夠定義多種遍歷方式。在迭代器模式中只須要用一個不一樣的迭代器來替換原有迭代器便可改變遍歷算法,咱們也能夠本身定義迭代器的子類以支持新的遍歷方式。
  2. 迭代器簡化了聚合類。因爲引入了迭代器,在原有的聚合對象中不須要再自行提供數據遍歷等方法,這樣能夠簡化聚合類的設計。
  3. 在迭代器模式中,因爲引入了抽象層,增長新的聚合類和迭代器類都很方便,無須修改原有代碼,知足「開閉原則」的要求。

2. 主要缺點

迭代器模式的主要缺點以下:

  1. 因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。
  2. 抽象迭代器的設計難度較大,須要充分考慮到系統未來的擴展,例如JDK內置迭代器Iterator就沒法實現逆向遍歷,若是須要實現逆向遍歷,只能經過其子類ListIterator等來實現,而ListIterator迭代器沒法用於操做Set類型的聚合對象。在自定義迭代器時,建立一個考慮全面的抽象迭代器並非件很容易的事情。

3. 適用場景

在如下狀況下能夠考慮使用迭代器模式:

  1. 訪問一個聚合對象的內容而無須暴露它的內部表示。將聚合對象的訪問與內部數據的存儲分離,使得訪問聚合對象時無須瞭解其內部實現細節。
  2. 須要爲一個聚合對象提供多種遍歷方式。
  3. 爲遍歷不一樣的聚合結構提供一個統一的接口,在該接口的實現類中爲不一樣的聚合結構提供不一樣的遍歷方式,而客戶端能夠一致性地操做該接口。

更多詳情請參考原文:

Reference: http://blog.csdn.net/lovelion/article/details/9992005

相關文章
相關標籤/搜索