1 minute read

반복자 패턴이란?


객체를 저장하는 방식은 보여주지 않으면서도 객체들에게 일일이 접근한 수 있게 해주는 방법.(OOP의 캡슐화)
알게모르게 사용하는 방법인데, C++에서의 stl의 iterator(vector, map, list)
일반적인 Array(배열)에서는 index로 배열을 참조하기 때문에 의미가 없지만 LinkedList라면 다릅니다.

사용하는 이유


  • 집합체 클래스의 응집도를 높여준다.
  • 내부에서 어떤 식으로 처리되는지 client가 일일히 알 필요 없이, 모든 항목에 접근 할 수 있게 해준다. (캡슐화)
  • 집합체 인터페이스 등의 구현이 간단해진다.

문제점&주의사항


  • 알고리즘 구현 부분에 따라 캡슐화에 위배할 수 도 있다.
  • 힙 메모리를 삭제하지 않아 오류가 발생할 수 있다.

사용법


UML_class_diagram
(이미지 출처 : https://ko.wikipedia.org/wiki/%EB%B0%98%EB%B3%B5%EC%9E%90_%ED%8C%A8%ED%84%B4 )

구조는 위의 class diagram과 같습니다.
구현 방법은 단순히 리스트 객체에 접근해서 새로운 내용을 삽입(또는 삭제) 하거나 반복하는 내용을 반복자 객체에 정의하는 것으로 구현할 수 있습니다.

샘플 코드


#include <iostream>
#include <vector>

// Iterator 인터페이스
class Iterator{
public:
    virtual ~Iterator() {}
    virtual void First() = 0;
    virtual void Next() = 0;
    virtual bool IsDone() const = 0;
    virtual int CurrentItem() const = 0;
};

// Concrete Iterator 클래스
class ConcreteIterator : public Iterator {
private:
    std::vector<int> collection_;
    int current_index_ = 0;

public:
    ConcreteIterator(const std::vector<int>& collection) : collection_(collection) {}

    void First() override {
        current_index_ = 0;
    }

    void Next() override {
        current_index_++;
    }

    bool IsDone() const override {
        return current_index_ >= collection_.size();
    }

    int CurrentItem() const override {
        if (IsDone()) {
            return -1; // 또는 예외 처리
        }
        return collection_[current_index_];
    }
};

// Aggregate 인터페이스
class Aggregate {
public:
    virtual ~Aggregate() {}
    virtual Iterator* CreateIterator() = 0;
};

// Concrete Aggregate 클래스
class ConcreteAggregate : public Aggregate {
private:
    std::vector<int> collection_;

public:
    ConcreteAggregate(const std::vector<int>& collection) : collection_(collection) {}

    Iterator* CreateIterator() override {
        return new ConcreteIterator(collection_);
    }
};

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    ConcreteAggregate aggregate(numbers);
    Iterator* iterator = aggregate.CreateIterator();

    for (iterator->First(); !iterator->IsDone(); iterator->Next()) {
        std::cout << iterator->CurrentItem() << " ";
    }
    std::cout << std::endl;

    delete iterator; // 중요: 동적 할당된 메모리 해제

    return 0;
}


Top