Iterator Design Pattern in Go

1. Definition

The Iterator Design Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

2. Problem Statement

Imagine having a collection of items, and you want to traverse through them. Directly exposing the internal structure of the collection can lead to issues such as tight coupling and unwanted modifications. Furthermore, different collections might have different ways to traverse through their items.

3. Solution

Use an iterator that encapsulates the logic of traversing each item in the collection. This decouples the collection from the logic needed to iterate through its elements.

4. Real-World Use Cases

1. Navigating through pages of a book.

2. Browsing songs in a music playlist.

3. Iterating over tree structures or graph nodes.

5. Implementation Steps

1. Create an Iterator interface that defines methods like Next(), HasNext(), etc.

2. Implement the Iterator interface for specific types of collections.

3. Use the Iterator to traverse the collection without having direct access to its underlying data structure.

6. Implementation in Go

// Step 1: Iterator interface
type Iterator interface {
	HasNext() bool
	Next() interface{}
}
// Concrete collection: Array of strings
type StringArray struct {
	items []string
	index int
}
// NewStringArray initializes a new string array
func NewStringArray(items []string) *StringArray {
	return &StringArray{items: items}
}
// HasNext checks if there's a next item
func (s *StringArray) HasNext() bool {
	return s.index < len(s.items)
}
// Next returns the next item and increments the index
func (s *StringArray) Next() interface{} {
	if s.HasNext() {
		item := s.items[s.index]
		s.index++
		return item
	}
	return nil
}
// Client code
func main() {
	items := []string{"apple", "banana", "cherry"}
	array := NewStringArray(items)
	for array.HasNext() {
		fmt.Println(array.Next())
	}
}

Output:

apple
banana
cherry

Explanation:

1. The Iterator interface is defined with the methods required for iteration.

2. StringArray is a concrete collection that implements this Iterator interface. It maintains an index to keep track of the traversal.

3. HasNext() checks if there are more items to iterate over, while Next() returns the next item and moves the index forward.

4. The client code creates a StringArray and uses its iterator methods to traverse through its items.

7. When to use?

Use the Iterator Pattern when:

1. You want to provide a way to access an aggregate object's elements without exposing its internal representation.

2. The collection has different ways of traversing its items, and you want to abstract this variation from the client.

3. You want to provide a uniform interface for traversing different aggregate structures (like arrays, trees, and graphs).


Comments