정말 오랜만에; 다시 디자인 패턴 정리. 좀 대충 만든 감이 없잖아 있다.. 이번 패턴은 이터레이터(반복자) 패턴!



- 컨테이너들을 같은 인터페이스로 활용하기 위해 사용

장점 1. 같은 인터페이스를 재활용 가능

장점 2. 내부 구현이 숨겨짐.



// 반복자 추상 클래스
template<typename T>
class DELIterator{
public:
    DELIterator() : _idx(0) {}
    virtual ~DELIterator() {};
    virtual bool hasNext() = 0;
    virtual T next() = 0;
    virtual void remove() = 0;
protected:
    int _idx;
};

// 배열 반복자(0을 사용하지 못함..)
template<typename T>
class DELArrayIterator : public DELIterator<T>{
public:
    DELArrayIterator(T* array, int size) : _array(array), _size(size) {}

    bool hasNext() override{
        if (_idx < _size && _array[_idx] != NULL){
            return true;
        }
        return false;
    }

    T next() override{
        if (hasNext()){
            return _array[_idx++];
        }
        return NULL;
    }
    void remove() override{
        _array[_idx - 1] = NULL;

        for (int i = _idx; i < _size; ++i){
            _array[i - 1] = _array[i];
            _array[i] = NULL;
        }
    }
private:
    T* _array; // void*의 포인터(배열)
    int _size; // 배열 크기
};

// 벡터 반복자
template<typename T>
class DELVectorIterator : public DELIterator<T>{
public:
    DELVectorIterator(std::vector<T> vector) : _vector(vector){}
    
    bool hasNext() override{
        if (_idx < _vector.size() && &_vector[_idx] != nullptr){
            return true;
        }
        return false;
    }

    T next(){
        if (hasNext()){
            return _vector.at(_idx++);
        }
        return NULL;
    }
    
    void remove() override{
        auto it = _vector.begin();
        for (int i = 0; i < _idx; ++i){
            ++it;
        }

        _vector.erase(it);
    }
private:
    std::vector<T> _vector;
};

void main(){
    int i[7] = { 1, 2, 3, 4, 5, 6 };
    vector<std::string> v;
    v.push_back("a");
    v.push_back("b");
    v.push_back("c");
    v.push_back("d");

    std::unique_ptr<DELArrayIterator<int>> iter(new DELArrayIterator<int>(i, 7));
    std::unique_ptr<DELVectorIterator<std::string>> iter2(new DELVectorIterator<std::string>(v));

    while (iter->hasNext() || iter2->hasNext()){
        if (iter->hasNext())
            cout << iter->next() << endl;
        if (iter2->hasNext())
            cout << iter2->next().c_str() << endl;
    }

    cout << endl << endl;

    iter.reset(new DELArrayIterator<int>(i, 7));
    iter2.reset(new DELVectorIterator<std::string>(v));

    int idx = 0;
    while (iter->hasNext() || iter2->hasNext()){
        if (iter->hasNext()){
            if (idx == 3){
                iter->remove();
            }
            cout << iter->next() << endl;
        }
        if (iter2->hasNext()){
            if (idx == 2){
                iter2->remove();
            }
            cout << iter2->next().c_str() << endl;
        }
        ++idx;
    }   
}