如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 DevTech Ascendancy Hub
本篇文章對應的是 Iterator 迭代設計 | 解說實現 | 物件導向設計
切割出遍歷物件,對於 不同物件可有不同遍歷方法
一個物件的遍歷如果透過內部自己提供,會使的該物件承擔過多責任 (也不易維護),但是如果提供給使用者就暴露了內部細節,這時就可以使用 跌代模式
提供一個方法取得容器物件的每個元素,又不對外暴露
Iterator 的定義
提供一種方法(界面),用來訪問一個容器中的所有元素,而不對外暴露細節
Iterator 角色介紹
角色 | 說明 |
---|---|
Aggregate (容器接口) | 提供一個類創建 Iterator 的方法 |
ConcreteAggreate | 實現容器的內容,內部有一個存放數據的容器 |
Iterator (迭代接口) | 負責訪問、遍歷容器的核心方法 |
ConcreteIterator | 實際去遍歷容器中的數據,內部會有一個 cursor 去紀錄使用者的操作行為 |
圖中 Aggregate 的方法對應 Java#Iterator 的方法如下表
Aggregate#Method | Java Iterator#Method |
---|---|
First() | - |
IsDone() | hasNext() |
Next() | next() |
CurrentItem() | - |
- | remove() |
Iterator 設計優點:隔離出物件儲存、物件遍歷兩項行為
單一職責:一個類負責一個責任;Iterator 類就是負責遍歷容器內的元素
界面隔離:最小化界面,不讓容器負擔遍歷的責任
Iterator 設計缺點:
非必要性:其最大的缺點其實就是大多數語言都對各自的容器內實現了 Iterator 的功能,我們幾乎很少有需要自己實現(當然除非一些特殊狀況或需求)
複雜化:自己時現實的複雜化,因為類的增加使用者使用起來會稍加複雜
Iterator
界面:這裡我們自己配合泛型實現一個 Iterator,有迭代容器的核心方法
interface MyIterator<T> {
fun hasNext(): Boolean
fun next(): T
fun remove() : Boolean
}
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
}
}
Aggregate
界面:提供使用者操控該容器的方法(add
, remove
…),但不提供直接遍歷容器的方法,改成提供 MyIterator 類
interface MyAggregate<T> {
fun add(item: T)
fun remove(item: T)
// 關聯 MyIterator
fun createIterator() : MyIterator<T>
}
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)
}
使用方式:以往是直接透過容器遍歷,現在改用取得 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()}")
}
}
}
接口 | 說明 / 功能 |
---|---|
Iterable | 從這個界面繼承的類可以表示為可以迭代的元素序列 |
Iterator | 可以表示為元素序列的集合或另一個實體的迭代器;允許順序訪問元素 |
物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)!
創建模式 - Creation Patterns
:
創建模式用於「物件的創建」,它關注於如何更靈活、更有效地創建對象。這些模式可以隱藏創建對象的細節,並提供創建對象的機制,例如單例模式、工廠模式… 等等,詳細解說請點擊以下連結
行為模式 - Behavioral Patterns
:
行為模式關注物件之間的「通信」和「職責分配」。它們描述了一系列對象如何協作,以完成特定任務。這些模式專注於改進物件之間的通信,從而提高系統的靈活性。例如,策略模式、觀察者模式… 等等,詳細解說請點擊以下連結
結構模式 - Structural Patterns
:
結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結
Java 設計模式
基礎進階