Iterator 迭代設計 | 解說實現 | 物件導向設計

Iterator 迭代設計 | 解說實現 | 物件導向設計

Overview of Content

本文將介紹 Iterator 迭代設計的基礎知識和實踐方法。

首先,將討論 Iterator 的使用場景,並深入探討其定義以及使用 UML 圖表來呈現。接下來,將探討 Iterator 設計的優缺點,幫助讀者更好地理解其在實踐中的應用。隨後,將深入研究 Iterator 的實現,包括標準實現的詳細解釋

最後,將看看 Java 中的 Iterator 與 Iterable 的功能,幫助讀者更好地理解 Java 中的迭代器機制。


Iterator 使用場景

A. 切割出遍歷物件,對於 不同物件可有不同遍歷方法

B. 一個物件的遍歷如果透過內部自己提供,會使的該物件承擔過多責任 (也不易維護),但是如果提供給使用者就暴露了內部細節,這時就可以使用 跌代模式

C. 提供一個方法取得容器物件的每個元素,又不對外暴露

Iterator 定義 & Iterator UML

● Iterator 的定義

提供一種方法(界面),用來訪問一個容器中的所有元素,而不對外暴露細節

● Iterator 角色介紹

角色說明
Aggregate (容器接口)提供一個類創建 Iterator 的方法
ConcreteAggreate實現容器的內容,內部有一個存放數據的容器
Iterator (迭代接口)負責訪問、遍歷容器的核心方法
ConcreteIterator實際去遍歷容器中的數據,內部會有一個 cursor 去紀錄使用者的操作行為

● 圖中 Aggregate 的方法對應 Java#Iterator 的方法如下表

Aggregate#MethodJava Iterator#Method
First()-
IsDone()hasNext()
Next()next()
CurrentItem()-
-remove()

Iterator 設計:優缺點

Iterator 設計優點:隔離出物件儲存、物件遍歷兩項行為

A. 單一職責:一個類負責一個責任;Iterator 類就是負責遍歷容器內的元素

B. 界面隔離:最小化界面,不讓容器負擔遍歷的責任

Iterator 設計缺點

A. 非必要性:其最大的缺點其實就是大多數語言都對各自的容器內實現了 Iterator 的功能,我們幾乎很少有需要自己實現(當然除非一些特殊狀況或需求)

B. 複雜化:自己時現實的複雜化,因為類的增加使用者使用起來會稍加複雜


Iterator 實現

Iterator 標準

A. Iterator 界面:這裡我們自己配合泛型實現一個 Iterator,有迭代容器的核心方法


interface MyIterator<T> {

    fun hasNext(): Boolean

    fun next(): T

    fun remove() : Boolean

}

B. CreteIterator:實做遍歷的方法;在這裡面有 cursor 紀錄使用者對於遍歷的操作


class MyConcreteIterator<T> constructor(val list: MutableList<T>): MyIterator<T> {

    private var cursor: Int = 0

    override fun hasNext(): Boolean {
        return cursor != list.size
    }

    override fun next(): T {
        // 移動指標
        return list[cursor++]
    }

    override fun remove(): Boolean {
        // 移動指標
        list.removeAt(cursor++)

        return true
    }

}

C. Aggregate 界面:提供使用者操控該容器的方法(add, remove...),但不提供直接遍歷容器的方法,改成提供 MyIterator 類


interface MyAggregate<T> {

    fun add(item: T)

    fun remove(item: T)

    // 關聯 MyIterator
    fun createIterator() : MyIterator<T>

}

D. ConcreteAggregate:它是一個容器類,保存數據並提供使用者操作數據的方法,但並不包括提供直接遍歷數據的方法(實做 MyIterator)

這個類負責串起 Iterator 的關係


class ConcreteAggregator: MyAggregate<String> {

    private val list = mutableListOf<String>()

    override fun add(item: String) {
        list.add(item)
    }

    override fun remove(item: String) {
        list.remove(item)
    }

    override fun createIterator(): MyIterator<String> {
        // 串起其關係
        return MyConcreteIterator(list.toMutableList())
    }

}

● 為何要使用 list.toMutableList() ?

這是一種 快照 作法,toMutableList() 會複製原本陣列的物件,而不是取得引用,這樣在使用上更安全,因為 Iterator 是取用副本的操作


public fun <T> Collection<T>.toMutableList(): MutableList<T> {
    return ArrayList(this)
}

E. 使用方式:以往是直接透過容器遍歷,現在改用取得 MyIterator 來遍歷

createIterator 方法是返回一個遍歷的對象,而不是容器內部持有對象,所以請不要在遍歷的過程中使用


// 以下使用嚴重錯誤!

while (createIterator().hasNext()) {
    println("item: ${createIterator().next()}")
}

fun main() {

    ConcreteAggregator().apply {
        add("Hello")
        add("World")
        add("Iterator")
        add("Design")
    }.run {
        val iterator = createIterator()

        while(iterator.hasNext()) {
            println("item: ${iterator.next()}")
        }
    }

}

Java

Iterator & Iterable 差異

接口說明 / 功能
Iterable從這個界面繼承的類可以表示為可以迭代的元素序列
Iterator可以表示為元素序列的集合或另一個實體的迭代器;允許順序訪問元


更多的物件導向設計

物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)!

設計建模 2 大概念- UML 分類、使用

物件導向設計原則 – 6 大原則(一)

物件導向設計原則 – 6 大原則(二)

創建、行為、結構型設計 8 個比較 | 包裝模式 | 最佳實踐

創建模式 Creation Patterns

創建模式 PK

創建模式 - Creation Patterns

結構模式 Structural Patterns

結構模式 PK

結構模式 - Structural Patterns

結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結

Bridge 橋接模式 | 解說實現 | 物件導向設計

Decorate 裝飾模式 | 解說實現 | 物件導向設計

Proxy 代理模式 | 解說實現 | 分析動態代理

Iterator 迭代設計 | 解說實現 | 物件導向設計

Facade 外觀、門面模式 | 解說實現 | 物件導向設計

Adapter 設計模式 | 解說實現 | 物件導向設計

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

發表迴響