Tuesday, September 10, 2024

Iterator Design Pattern in C#

The Iterator Design Pattern is a behavioral design pattern that allows sequential access to the elements of an aggregate object (i.e., collection) without exposing its underlying representation. That means using the Iterator Design Pattern, we can access the elements of a collection sequentially without knowing its internal representations. This pattern provides a uniform interface for traversing different data structures.

The collections in C#, like List, ArrayList, Array, etc., are containers containing many objects. In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the elements of the container.

Components of Iterator Pattern

  • Iterator: The interface that defines the methods for traversing the collection.
  • Concrete Iterator: The class that implements the iterator interface and performs the actual traversal.
  • Aggregate: The interface for the collection that provides a method to create an iterator.
  • Concrete Aggregate: The class that implements the aggregate interface and returns an instance of the concrete iterator.

Example Implementation in C#

Let's create a simple example using the Iterator Pattern. We’ll define a custom collection called BookCollection that holds a list of Book objects. We will implement an iterator to traverse the collection.

Define Book Class
namespace IteratorDesignPattern.Model
{
    public class Book
    {
        public string Title { get; }
        public string Author { get; }

        public Book(string title, string author)
        {
            Title = title;
            Author = author;
        }
    }
}
Define the IIterator interface
namespace IteratorDesignPattern.Iterator
{
    public interface IIterator<T>
    {
        bool HasNext();
        T Next();
    }
}
Implement the BookIterator class
using IteratorDesignPattern.Model;

namespace IteratorDesignPattern.Iterator
{
    public class BookIterator : IIterator<Book>
    {
        private readonly List<Book> _books;
        private int _position = 0;

        public BookIterator(List<Book> books)
        {
            _books = books;
        }

        public bool HasNext()
        {
            return _position < _books.Count;
        }

        public Book Next()
        {
            if (!HasNext())
            {
                return null;
            }

            return _books[_position++];
        }
    }
}
Define the IAggregate interface
using IteratorDesignPattern.Iterator;

namespace IteratorDesignPattern.Aggregator
{
    public interface IAggregate<T>
    {
        IIterator<T> CreateIterator();
    }
}
Implement the BookCollection class
using IteratorDesignPattern.Iterator;
using IteratorDesignPattern.Model;

namespace IteratorDesignPattern.Aggregator
{
    public class BookCollection : IAggregate<Book>
    {
        private readonly List<Book> _books = new List<Book>();

        public void AddBook(Book book)
        {
            _books.Add(book);
        }

        public IIterator<Book> CreateIterator()
        {
            return new BookIterator(_books);
        }
    }
}
Using the Iterator(Program.cs)
using IteratorDesignPattern.Aggregator;
using IteratorDesignPattern.Iterator;
using IteratorDesignPattern.Model;

BookCollection bookCollection = new BookCollection();
bookCollection.AddBook(new Book("Do Epic Shit", "Ankur Wariko"));
bookCollection.AddBook(new Book("To Kill a Mockingbird", "Harper Lee"));
bookCollection.AddBook(new Book("1984", "George Orwell"));

IIterator<Book> iterator = bookCollection.CreateIterator();

while (iterator.HasNext())
{
    Book book = iterator.Next();
    Console.WriteLine($"{book.Title} by {book.Author}");
}
Console.ReadLine();

Output

Iterator Design Pattern in C#

Explanation

  1. Book Class: Represents a book with a title and an author.

  2. IIterator Interface: Defines the methods HasNext (to check if there are more elements) and Next (to get the next element).

  3. BookIterator Class: Implements the IIterator interface. It maintains the current position in the collection and provides methods to traverse the list of books.

  4. IAggregate Interface: Declares a method CreateIterator to return an iterator for the collection.

  5. BookCollection Class: Implements the IAggregate interface and provides a way to add books to the collection. It also returns an iterator to traverse the books.

  6. Using the Iterator: In Program.cs we use the iterator to traverse the BookCollection. It prints each book's title and author.

Benefits of the Iterator Pattern

  • Encapsulation: The Iterator pattern hides the internal structure of the collection, allowing you to traverse it without exposing its implementation details.
  • Flexibility: You can traverse different types of collections using the same interface, making your code more reusable.
  • Separation of Concerns: By separating the collection and the traversal logic, the pattern promotes cleaner code and better maintainability.

Conclusion

The Iterator pattern is a powerful tool for managing collections in a flexible and reusable manner. By implementing this pattern in C#, you can simplify the traversal of complex collections and keep your codebase clean and maintainable.

The full source code is available here:

iterator design pattern example

Happy coding!! 😊

No comments:

Post a Comment

^ Scroll to Top