DEV Community

Oluwasanmi Aderibigbe
Oluwasanmi Aderibigbe

Posted on • Updated on

Head First Design Pattern : 8 of 10

I just learnt a new design from the Head First Design Pattern book. Today, I learnt about the Iterator pattern.

According to the head-first design pattern, the Iterator pattern is a pattern that allows you to access the elements of a collection sequentially without exposing its underlying representation. It allows you to extract the transversal logic of collections. It does so in a way that it makes transversing elements of any collection easier.

Implementing the Iterator is pretty straightforward

  1. Define an iterator interface
interface Iterator<out T> {
    fun hasNext() : Boolean
    fun next() : T
}
Enter fullscreen mode Exit fullscreen mode

The Iterator interface below has two methods. The hasNext and the next. The hasNext is used to check if the collection has items remaining while the next is used to get the next item from the collection. Instead of creating your implementation of the Iterator interface, you can also use the Iterator interface in Java.

2.Create a class that implements the Iterator interface. As you can see they all contain different kinds of collections. Without the Iterator pattern, you'll have to transverse each collection separately.

class MangaIterator(val mangas: List<Manga>) : Iterator<Manga> {
    var position: Int = 0
        private set

    override fun hasNext(): Boolean {
        return if (position >= mangas.size || mangas.getOrNull(position) == null) false else true
    }

    override fun next(): Manga {
        val manga = mangas[position]
        position += 1
        return  manga
    }
}
Enter fullscreen mode Exit fullscreen mode

class AnimeIterator(val animes: Array<Anime>) : Iterator<Anime>{
    var position: Int = 0
        private set

    override fun hasNext(): Boolean {
        return if (position >= animes.size || animes.getOrNull(position) == null) false else true
    }

    override fun next(): Anime {
        val manga = animes[position]
        position += 1
        return  manga
    }
}
Enter fullscreen mode Exit fullscreen mode
class NovelIterator(val novels: HashMap<String, Novel>): Iterator<Novel> {
    var position: Int = 0
        private set

    override fun hasNext(): Boolean {
        return if (position >=    novels.values.size ||  novels.values.elementAt(position) == null) false else true

    }

    override fun next(): Novel {
        val novel = novels.values.elementAt(position)
        position += 1
        return  novel
    }
}
Enter fullscreen mode Exit fullscreen mode
class TrackerApp() {
    fun <T> print(iterator: Iterator<T>) {
        while (iterator.hasNext()) {
            println(iterator.next())
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
fun main() {
    val manga = listOf<Manga>(
        Manga("Relife", "Slice of Life"),
        Manga("Koe no katachi", "Slice of Life"),
        Manga("Vagabond", "Action")
    )
    val anime = arrayOf(Anime("Konosuba", "Comedy"), Anime("Miss Koyobashi's Dragon maid", "Comedy"))
    val novels =
        hashMapOf<String, Novel>("Markus Zusak" to Novel("The book thief"), "Brandon Sanderson" to Novel("Mistborn"))

    val mangaIterator = MangaIterator(manga)
    val animeIterator = AnimeIterator(anime)
    val novelIterator = NovelIterator(novels)

    val trackerApp = TrackerApp()
    trackerApp.print(mangaIterator)
    trackerApp.print(animeIterator)
    trackerApp.print(novelIterator)

Manga(name=Relife, genre=Slice of Life)
Manga(name=Koe no katachi, genre=Slice of Life)
Manga(name=Vagabond, genre=Action)
Anime(name=Konosuba, genre=Comedy)
Anime(name=Miss Koyobashi's Dragon maid, genre=Comedy)
Novel(name=The book thief)
Novel(name=Mistborn)

}
Enter fullscreen mode Exit fullscreen mode

Since the logic for transversing the collection has been encapsulated within an Iterator class. The TrackerApp can traverse any kind of collection so fat they implement the Iterator interface.
The Iterator pattern shines when you have transverse different kinds of collections.

Discussion (0)