프로그래밍 이론/디자인 패턴

16. [Design Pattern] 이터레이터(Iterator) 패턴

NewtronVania 2024. 1. 14. 23:54

이터레이터 패턴

컬렉션(: 리스트, 스택, 트리 ) 요소를 순회하는 표준 방법을 제공하는 디자인 패턴. 집합 객체를 순회하는 클라이언트 코드를 변경하지 않고 컬렉션들에 접근할 수 있는 다양한 순회 방법을 제공한다.


구조

  • Iterator -  다음 요소에 접근하거나, 다음 요소가 있는지 확인하는 메소드 등을 정의한다.
  • ConcreteIterator - Iterator 인터페이스를 구현하는 클래스. 컬렉션의 특정 구현 방식(: 배열, 연결 리스트) 따라 이터레이터의 순회 로직을 구현한다.
  • Aggregate -Iterator 객체를 생성하는 메소드를 정의하는 클래스.
  • ConcreteAggregate -Aggregate 인터페이스를 구현하는 클래스. 실제 컬렉션을 관리하며, 해당 컬렉션에 대한 Iterator 생성하는 로직을 포함한다.

기본 인터페이스

public interface IIterator<T>
{
    bool HasNext();
    T Next();
}

public class ConcreteIterator<T> : IIterator<T>
{
    private readonly List<T> _collection;
    private int _currentIndex = 0;

    public ConcreteIterator(List<T> collection)
    {
        _collection = collection;
    }

    public bool HasNext()
    {
        return _currentIndex < _collection.Count;
    }

    public T Next()
    {
        if (!HasNext())
        {
            throw new InvalidOperationException("No more elements in collection");
        }

        return _collection[_currentIndex++];
    }
}

public interface IAggregate<T>
{
    IIterator<T> CreateIterator();
}

public class ConcreteAggregate<T> : IAggregate<T>
{
    private readonly List<T> _collection = new List<T>();

    public IIterator<T> CreateIterator()
    {
        return new ConcreteIterator<T>(_collection);
    }

    public void Add(T item)
    {
        _collection.Add(item);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var aggregate = new ConcreteAggregate<string>();
        aggregate.Add("Item 1");
        aggregate.Add("Item 2");
        aggregate.Add("Item 3");

        var iterator = aggregate.CreateIterator();

        while (iterator.HasNext())
        {
            var item = iterator.Next();
            Console.WriteLine(item);
        }
    }
}

왜 사용해야 할까?

패턴의 핵심은 컬렉션의 순회 로직을 컬렉션 자체로부터 분리하는 것이다. 이로 인해 컬렉션의 구현 방식이 변경되더라도, 클라이언트 코드는 영향을 받지 않는다. 클라이언트는 일관된 방식으로 다양한 컬렉션 타입을 처리할 있다.

이터레이터 패턴은 이터레이터(Iterator) 집합체(Aggregate) 구성 요소로 이루어져 있다.

이터레이터는 컬렉션의 요소에 접근하고 순회하는 인터페이스를 제공한다. 인터페이스는 일반적으로 next(), hasNext() 같은 메서드를 포함하여, 컬렉션의 다음 요소를 검색하고, 이상 요소가 없는지 확인한다.

public interface IIterator<T>
{
    bool HasNext();
    T Next();
}

집합체는 이터레이터 인스턴스를 생성하는 역할을 하며, 실제 컬렉션 데이터를 관리한다

public interface IAggregate<T>
{
    IIterator<T> CreateIterator();
}

 

장점

  1. 집합 객체의 컬렉션을 캡슐화할 수 있다.
  2. 일관된 인터페이스를 사용하여 여러 형태의 집합 구조를 순회할 있다.
  3. 집합 객체가 가지고 있는 객체들에 대해 손쉽게 접근할 수 있다

단점

  1. 간단한 컬렉션에 대해 이터레이터 패턴을 사용하면 불필요한 오버헤드가 발생할 수 있다.
  2. 클래스가 늘어나고 복잡도가 증가한다.

 

참고자료

 

GoF의 디자인 패턴 - 예스24

이 책은 디자인 패턴을 다룬 이론서로 디자인 패턴의 기초적이고 전반적인 내용을 학습할 수 있다.

www.yes24.com