Iterator Pattern #
Dalam dunia pengembangan perangkat lunak, desain pola (design pattern) merupakan solusi umum yang telah teruji untuk masalah yang sering muncul dalam pembuatan sistem. Salah satu kategori design pattern adalah behavioral pattern, yang fokus pada komunikasi dan tanggung jawab antara objek.
Iterator Pattern adalah salah satu behavioral pattern yang sangat berguna ketika kita ingin mengakses elemen-elemen dalam sebuah koleksi secara berurutan tanpa mengekspos representasi internal koleksi tersebut.
Apa itu Iterator Pattern? #
Iterator Pattern adalah pola desain yang menyediakan cara untuk mengakses elemen-elemen dari sebuah objek agregat (koleksi) secara berurutan tanpa mengekspos struktur internalnya. Pola ini memungkinkan kita untuk memisahkan logika traversal (penjelajahan) dari struktur data itu sendiri.
Secara sederhana, Iterator Pattern memisahkan “cara mengakses” dari “cara menyimpan data”.
Komponen Utama: #
- Iterator: Interface yang mendefinisikan metode traversal seperti
Next()danHasNext(). - Concrete Iterator: Implementasi dari iterator untuk koleksi tertentu.
- Aggregate: Interface yang menyediakan metode untuk membuat iterator.
- Concrete Aggregate: Implementasi dari koleksi yang dapat diiterasi.
Tujuan dari Pattern #
- Mengakses elemen dari koleksi tanpa mengungkapkan representasi internal.
- Menyederhanakan traversal objek koleksi yang kompleks.
- Mendukung multiple iterasi secara bersamaan pada koleksi yang sama.
- Memisahkan logika traversal dari struktur data.
Kapan Cocok Digunakan? #
- Ketika sebuah koleksi memiliki struktur internal kompleks dan traversal tidak boleh mengekspos detail internal.
- Saat dibutuhkan beberapa cara untuk menelusuri koleksi.
- Jika ingin mendukung multiple traversal pada koleksi yang sama secara bersamaan.
Contoh Implementasi (Golang) #
Berikut contoh implementasi Iterator Pattern pada koleksi sederhana BookCollection:
package main
import (
"fmt"
)
// Book struct
type Book struct {
Title string
}
// Iterator interface
type Iterator interface {
HasNext() bool
Next() *Book
}
// Aggregate interface
type Collection interface {
CreateIterator() Iterator
}
// Concrete Aggregate
type BookCollection struct {
books []*Book
}
func (c *BookCollection) AddBook(book *Book) {
c.books = append(c.books, book)
}
func (c *BookCollection) CreateIterator() Iterator {
return &BookIterator{
collection: c,
index: 0,
}
}
// Concrete Iterator
type BookIterator struct {
collection *BookCollection
index int
}
func (i *BookIterator) HasNext() bool {
return i.index < len(i.collection.books)
}
func (i *BookIterator) Next() *Book {
if i.HasNext() {
book := i.collection.books[i.index]
i.index++
return book
}
return nil
}
func main() {
collection := &BookCollection{}
collection.AddBook(&Book{Title: "Clean Code"})
collection.AddBook(&Book{Title: "Design Patterns"})
collection.AddBook(&Book{Title: "The Pragmatic Programmer"})
iterator := collection.CreateIterator()
for iterator.HasNext() {
book := iterator.Next()
fmt.Println(book.Title)
}
}
Output: #
Clean Code
Design Patterns
The Pragmatic Programmer
Best Practices #
- Pisahkan traversal dari koleksi: Jangan letakkan logika traversal di dalam struktur koleksi.
- Dukung multiple iterator: Pastikan koleksi bisa membuat beberapa iterator tanpa mengganggu satu sama lain.
- Gunakan interface: Dengan mendefinisikan
IteratordanCollectioninterface, implementasi dapat lebih fleksibel. - Sederhanakan traversal: Iterator harus fokus pada traversal, bukan manipulasi koleksi.
- Pertimbangkan lazy evaluation: Untuk koleksi besar, iterator bisa men-generate elemen hanya saat dibutuhkan untuk menghemat memori.
Penutup #
Iterator Pattern memudahkan pengembang untuk mengakses elemen-elemen dalam koleksi tanpa mengkhawatirkan struktur internalnya. Dengan memisahkan traversal dari koleksi, kode menjadi lebih fleksibel, modular, dan mudah di-maintain. Pola ini sangat bermanfaat dalam aplikasi yang memerlukan multiple traversal atau struktur data kompleks.