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

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

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

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

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

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

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

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

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

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

interface Iterator<T> {
    fun hasNext(): Boolean
    fun next(): T
}

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

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

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

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。但在这里我们来看看轮子的大概:

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]
}

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

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!

你可能感兴趣的:(面试,开发基础,Android,夯实基础,android,设计模式,迭代器模式)