Design patterns are proven solutions to software design problems. They help improve code quality, promote reusability, and increase maintainability. We use them to save time and produce quality, extensible and flexible code. In this article, we are going to introduce the Iterator design pattern.
The Iterator design pattern is a behavioral pattern that provides a way to iterate through the elements of a collection one by one without paying attention to the details of the collection. This pattern promotes encapsulation and allows the internal structure of the collection to be changed without affecting the client code. For example, if the collection structure is changed from an array to a list, the client codes will not change.
The Iterator design pattern consists of four main components:
Below is an example of the Iterator pattern in C#:
//Iterator interface
public interface IIterator
{
bool HasNext();
object Next();
}
//Concrete Iterator class
public class BookIterator : IIterator
{
private readonly List<Book> _books;
private int _position;
public BookIterator(List<Book> books)
{
_books = books;
_position = 0;
}
public bool HasNext()
{
return _position < _books.Count;
}
public object Next()
{
if (!HasNext())
return null;
var book = _books[_position];
_position++;
return book;
}
}
//Aggregate interface
public interface IAggregate
{
IIterator CreateIterator();
}
//Concrete Aggregate class
public class BookCollection : IAggregate
{
private readonly List<Book> _books;
public BookCollection()
{
_books = new List<Book>();
}
public void AddBook(Book book)
{
_books.Add(book);
}
public IIterator CreateIterator()
{
return new BookIterator(_books);
}
}
//Book class
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
//Client code
public class Client
{
public void Main()
{
var bookCollection = new BookCollection();
bookCollection.AddBook(new Book { Title = "The Catcher in the Rye", Author = "J.D. Salinger" });
bookCollection.AddBook(new Book { Title = "To Kill a Mockingbird", Author = "Harper Lee" });
bookCollection.AddBook(new Book { Title = "1984", Author = "George Orwell" });
var iterator = bookCollection.CreateIterator();
while (iterator.HasNext())
{
var book = iterator.Next() as Book;
Console.WriteLine($"Title: {book.Title}, Author: {book.Author}");
}
}
}
In this example, we first create an Iterator interface that defines the access and navigation methods of the collection elements. Then we create a Concrete Iterator class called BookIterator that implements the Iterator interface. This class creates an array of books and maintains the current position while iterating through the array.
Then we create an Aggregate interface called IAggregate that defines the creation method of an Iterator object.
Next, we create a Concrete Aggregate class called BookCollection that implements the IAggregate interface. This class holds a list of books and provides a method to add books to the collection. It also creates a BookIterator object that is used to iterate through the collection.
Finally, the client code creates a collection of Books using the BookCollection class, and whenever we need to scroll through this collection, we create an Iterator object using the CreateIterator method, which provides navigation facilities.
To read about other design patterns, you can use the list below. There is also a code repository on GitHub that includes all the design patterns.
I am Reza Babakhani, a software developer. Here I write my experiences, opinions and suggestions about technology. I hope that what I write is useful for you.
leave a comment