安卓常见设计模式11------迭代器模式(Kotlin版)

1. W1 是什么,什么是迭代器模式?​

  1. 迭代器模式(Iterator Pattern)是一种行为设计模式,它提供了一种遍历集合对象的方法,而无需暴露集合的内部表示。
  2. 迭代器模式由两个主要角色组成:迭代器(Iterator)和集合(Collection)。

2. W2 为什么,为什么需要使用迭代器模式,能给我们编码带来什么好处?​

  1. 抽象了遍历过程:迭代器模式将遍历过程抽象为一个独立的迭代器对象,封装了遍历的细节和逻辑。这样,可以通过迭代器对象来遍历集合,而无需直接操作集合本身。这样做的好处是,可以隐藏集合的内部实现细节,提供一种统一的遍历接口,使代码更加模块化和可维护

  2. 支持不同类型的集合:迭代器模式可以适用于不同类型的集合,包括自定义的数据结构。通过实现迭代器接口,可以定义不同集合的迭代器,使它们具有相同的遍历方式和接口。这样,可以在不改变遍历代码的情况下,切换不同类型的集合或数据结构。

  3. 支持并发遍历:在某些情况下,可能需要在多个线程中同时遍历集合。使用迭代器模式,可以创建线程安全的迭代器,确保在并发环境下遍历的正确性和一致性。

  4. 支持遍历过程中的操作 :迭代器模式允许在遍历过程中执行操作,如删除元素或修改集合。通过迭代器的remove()方法,可以安全地删除集合中的元素,而不会导致遍历过程中的异常或错误

3. W3,如何使用?下面是代码示例:

迭代器(Iterator):它是一个接口或抽象类,定义了遍历集合对象的方法,例如hasNext()用于检查是否还有下一个元素,next()用于获取下一个元素。

kotlin 复制代码
interface Iterator<T> {
    fun hasNext(): Boolean
    fun next(): T
}

集合(Collection):它是一个包含元素的集合对象,可以是一个列表、数组或其他数据结构。集合提供了创建迭代器的方法,例如iterator()。

kotlin 复制代码
interface Collection<T> {
    fun iterator(): Iterator<T>
}

通过实现迭代器接口和集合接口,我们可以创建可迭代的集合,并使用迭代器逐个访问集合中的元素:

kotlin 复制代码
class MyCollection<T>(private val items: List<T>) : Collection<T> {
    override fun iterator(): Iterator<T> {
        return MyIterator()
    }

    private inner class MyIterator : Iterator<T> {
        private var currentIndex = 0

        override fun hasNext(): Boolean {
            return currentIndex < items.size
        }

        override fun next(): T {
            if (!hasNext()) {
                throw NoSuchElementException()
            }
            return items[currentIndex++]
        }
    }
}

// 使用迭代器遍历集合
val collection = MyCollection(listOf(1, 2, 3, 4, 5))
val iterator = collection.iterator()
while (iterator.hasNext()) {
    val item = iterator.next()
    println(item)
}

或许很多小伙伴会认为迭代器可有可无,毕竟一个for循环就能搞定的事,何必这么麻烦呢?

设计模式设计出来那就是用来解决问题的,不知道大家有没有遇到这个问题:当我们一边遍历一个可修改的列表的时候,一边移除列表的元素的话,使用for循环是会报错的。迭代器就很好地适配这个问题,一般像Kotlin语言的list自带有lterator。但在这里我们来看看轮子的大概:

kotlin 复制代码
interface Iterator<T> {
    fun hasNext(): Boolean
    fun next(): T
    fun remove()
}

interface Collection<T> {
    fun iterator(): Iterator<T>
}

class MyCollection<T>(private val items: MutableList<T>) : Collection<T> {
    override fun iterator(): Iterator<T> {
        return MyIterator()
    }

    private inner class MyIterator : Iterator<T> {
        private var currentIndex = 0
        private var lastReturnedIndex = -1

        override fun hasNext(): Boolean {
            return currentIndex < items.size
        }

        override fun next(): T {
            if (!hasNext()) {
                throw NoSuchElementException()
            }
            lastReturnedIndex = currentIndex
            return items[currentIndex++]
        }

        override fun remove() {
            if (lastReturnedIndex == -1) {
                throw IllegalStateException()
            }
            items.removeAt(lastReturnedIndex)
            currentIndex--
            lastReturnedIndex = -1
        }
    }
}

fun main() {

    // 使用迭代器遍历集合
    val collection = MyCollection(mutableListOf(1, 2, 3, 4, 5))
    val iterator = collection.iterator()
    while (iterator.hasNext()) {
        val item = iterator.next()
        println(item)
        if (item == 3) {
            iterator.remove()
        }
    }
    println(collection.items) // prints [1, 2, 4, 5]
}

似乎还是用处不大,那如果加上多线程呢?

kotlin 复制代码
import java.util.concurrent.locks.ReentrantReadWriteLock

class MyCollection<T>(private val items: MutableList<T>) : Collection<T> {
    private val lock = ReentrantReadWriteLock()

    override fun iterator(): Iterator<T> {
        return MyIterator()
    }

    private inner class MyIterator : Iterator<T> {
        private var currentIndex = 0
        private var lastReturnedIndex = -1

        override fun hasNext(): Boolean {
            lock.readLock().lock()
            try {
                return currentIndex < items.size
            } finally {
                lock.readLock().unlock()
            }
        }

        override fun next(): T {
            lock.readLock().lock()
            try {
                if (!hasNext()) {
                    throw NoSuchElementException()
                }
                lastReturnedIndex = currentIndex
                return items[currentIndex++]
            } finally {
                lock.readLock().unlock()
            }
        }

        override fun remove() {
            lock.writeLock().lock()
            try {
                if (lastReturnedIndex == -1) {
                    throw IllegalStateException()
                }
                items.removeAt(lastReturnedIndex)
                currentIndex--
                lastReturnedIndex = -1
            } finally {
                lock.writeLock().unlock()
            }
        }
    }

    fun add(item: T) {
        lock.writeLock().lock()
        try {
            items.add(item)
        } finally {
            lock.writeLock().unlock()
        }
    }

    fun remove(item: T) {
        lock.writeLock().lock()
        try {
            items.remove(item)
        } finally {
            lock.writeLock().unlock()
        }
    }

    fun size(): Int {
        lock.readLock().lock()
        try {
            return items.size
        } finally {
            lock.readLock().unlock()
        }
    }
}

fun main() {

    // 使用迭代器遍历集合
    val collection = MyCollection(mutableListOf(1, 2, 3, 4, 5))
    val iterator = collection.iterator()
    while (iterator.hasNext()) {
        val item = iterator.next()
        println(item)
        if (item == 3) {
            iterator.remove()
        }
    }
    println(collection.size()) // prints 4

    // 在多个线程中添加和删除元素
    val thread1 = Thread {
        collection.add(6)
        collection.add(7)
    }
    val thread2 = Thread {
        collection.remove(4)
        collection.remove(5)
    }
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    println(collection.size()) // prints 4
}

那么我们在经常使用的RecyclerView中将数据源collection替换成collection.iterator()的话,不就能支持多线程了哇。

Thank you for your reading, best regards!😄😄

相关推荐
静水流深_沧海一粟2 小时前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder2 小时前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿巴斯甜8 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker8 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
阿星AI工作室9 小时前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
xq95279 小时前
Andorid Google 登录接入文档
android
黄林晴11 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android