Thinking Different







Iterator Pattern - 반복자 패턴


  • 내부 구현에 대한 이해 없이 자료의 집합체(List, Stack 등)을 탐색할 수 있게 해주는 패턴이다
  • C++ STL의 Iterator , java.util.Collection 의 Iterator 메소드 등이 있다

[출처] Iterator 패턴|작성자 요피엘







샘플 예시) LinkList를 활용한 Iterator 구현 샘플



샘플 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#if _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
 
//------------------------------------------------------------------
// Element 클래스
class Element
{
public:
    Element(tstring str) : data(str) {}
    tstring data;
};
 
//------------------------------------------------------------------
// Aggregate 인터페이스
class Aggregate
{
public:
    Aggregate() : mTotalCount(0) {}
 
public:
    friend class Iterator;    // 전방선언
    virtual Iterator* createIterator() = 0;
    virtual void AddNext(Element* pNewElement, Element* pElement = 0) = 0;
    virtual void Remove(Element* pElement) = 0;
    virtual Element* GetItem(int pos) = 0;
 
    int GetCount() const { return mTotalCount; }
 
protected:
    int mTotalCount;
};
 
//------------------------------------------------------------------
// LinkList 상속 클래스
class LinkList : public Aggregate
{
public:
    LinkList() : pFirst(NULL) {}
 
    struct LinkedElement
    {
        LinkedElement(Element* pItem = 0, LinkedElement* pNext_ = 0)
            : pData(pItem), pNext(pNext_) {}
        Element* pData;
        LinkedElement* pNext;
    };
 
public:
 
    Iterator* createIterator();
    void AddNext(Element* pNewElement, Element* pElement = 0)
    {
        if (pFirst == 0)
        {
            pFirst = new LinkedElement(pNewElement);
        }
        else if (pElement == 0 || pElement == pFirst->pData)
        {
            LinkedElement* pTmp = pFirst->pNext;
            pFirst->pNext = new LinkedElement(pNewElement, pTmp);
        }
        else
        {
            LinkedElement* pPrev = 0;
            LinkedElement* pTmp = pFirst;
            while (pTmp != 0 && pTmp->pData != pElement)
            {
                pPrev = pTmp;
                pTmp = pTmp->pNext;
            }
 
            if (pTmp != 0)
            {
                LinkedElement* pTmp2 = pTmp->pNext;
                pTmp->pNext = new LinkedElement(pNewElement, pTmp2);
            }
            else
                pPrev->pNext = new LinkedElement(pNewElement, 0);
        }
 
        mTotalCount++;
    }
    void Remove(Element* pElement)
    {
        if (pElement == 0)
            return;
 
        LinkedElement* pPrev = 0;
        LinkedElement* pTmp = pFirst;
        while (pTmp != 0 && pTmp->pData != pElement)
        {
            pPrev = pTmp;
            pTmp = pTmp->pNext;
        }
 
        if (pTmp != 0)
        {
            if (pTmp == pFirst)
            {
                delete pTmp;
                pFirst = 0;
            }
            else
            {
                pPrev->pNext = pTmp->pNext;
                delete pTmp;
            }
 
            mTotalCount--;
        }
    }
 
    Element* GetItem(int pos)
    {
        int cnt = 0;
        LinkedElement* pTmp = pFirst;
        while (pTmp != 0 && cnt != pos)
        {
            pTmp = pTmp->pNext;
            cnt++;
        }
 
        if (pTmp != 0)
            return pTmp->pData;
        else
            return 0;
    }
 
private:
    LinkedElement* pFirst;
};
 
//------------------------------------------------------------------
// Iterator 인터페이스
class Iterator
{
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool isDone() = 0;
    virtual Element* GetItem() = 0;
};
 
//------------------------------------------------------------------
// ListIterator 상속 클래스
class ListIterator : public Iterator
{
public:
    ListIterator(Aggregate* a) : pAggregate(a), curPos(0) {}
    ~ListIterator() { if (pAggregate) delete pAggregate; }
 
public:
    void first() override { curPos = 0; }
    void next() override { curPos++; }
    bool isDone() override { return curPos >= pAggregate->GetCount(); }
    Element* GetItem() override { return pAggregate->GetItem(curPos); }
 
private:
    Aggregate* pAggregate;
    int curPos;
};
 
//------------------------------------------------------------------
// 전방 선언으로 인한 Iterator 클래스 아래 구현 작성
Iterator* LinkList::createIterator()
{
    return new ListIterator(this);
}
 
//------------------------------------------------------------------
// IteratorPtr 클래스
class IteratorPtr
{
public:
    IteratorPtr(Iterator* it) : pIter(it) {}
    ~IteratorPtr() { delete pIter; }
 
    Iterator* operator-> () { return pIter; }
    Iterator& operator* () { return *pIter; }
 
protected:
    IteratorPtr(const IteratorPtr& rhs);
    IteratorPtr& operator=(const IteratorPtr& rhs);
 
private:
    Iterator* pIter;
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    Element a("a"), b("b"), c("c"), d("d"), e("e");
 
    LinkList list;
 
    list.AddNext(&a);
    list.AddNext(&b, &a);
    list.AddNext(&c, &b);
    list.AddNext(&d, &c);
    list.AddNext(&e, &d);
 
    IteratorPtr it((ListIterator*)list.createIterator());
 
    for (it->first(); !it->isDone(); it->next())
        cout << it->GetItem()->data << endl;
 
    return 0;
}




예제를 통한 반복자 패턴(Iterator Pattern) 알아보기



예제) Stack 클래스에 Iterator 패턴 적용하기


위의 기본 샘플 예제는 LinkList 를 기준으로 Iterator 패턴을 적용한 것이라면, 이 예제는 Stack을 적용하여 코드상으로도 좀 더 짧고 쉽게 볼 수 있는 예제로 하였다


예제 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#if _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
 
//------------------------------------------------------------------
// Element 클래스
class Element
{
public:
    Element(tstring str) : data(str) {}
    tstring data;
};
 
//------------------------------------------------------------------
// Aggregate 인터페이스
class Aggregate
{
public:
    Aggregate() : mStackPoint(-1) {}
 
public:
    friend class Iterator;    // 전방선언
    virtual Iterator* createIterator() = 0;
    virtual void push(Element* pElement) = 0;
    virtual Element* pop() = 0;
    virtual Element* GetElement(int index) = 0;
    bool isEmpty() { return mStackPoint == -1; }
    int GetStackPoint() { return mStackPoint; }
 
protected:
    int mStackPoint;
};
 
//------------------------------------------------------------------
// LinkList 상속 클래스
const int STACK_SIZE = 10;
class Stack : public Aggregate
{
public:
    Iterator* createIterator();
 
    void push(Element* pElement)
    { 
        if (mStackPoint + 1 < STACK_SIZE)
            mItem[++mStackPoint] = pElement;
        else
            cout << "Stack is Full!" << endl;
    }
 
    Element* pop()
    {
        if (!isEmpty())
            return mItem[mStackPoint--];
        else
            cout << "Stack is Empty!" << endl;
 
        return NULL;
    }
 
    Element* GetElement(int index) { return mItem[index]; }
 
private:
    Element* mItem[STACK_SIZE];
};
 
//------------------------------------------------------------------
// Iterator 인터페이스
class Iterator
{
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool isDone() = 0;
    virtual Element* GetItem() = 0;
};
 
//------------------------------------------------------------------
// ListIterator 상속 클래스
class StackIterator : public Iterator
{
public:
    StackIterator(Aggregate* a) : pAggregate(a), mIndex(0) {}
    ~StackIterator() { if (pAggregate) delete pAggregate; }
 
public:
    void first() override { mIndex = 0; }
    void next() override { mIndex++; }
    bool isDone() override { return mIndex == pAggregate->GetStackPoint() + 1; }
    Element* GetItem() override { return pAggregate->GetElement(mIndex); }
 
private:
    Aggregate* pAggregate;
    int mIndex;
};
 
//------------------------------------------------------------------
// 전방 선언으로 인한 Iterator 클래스 아래 구현 작성
Iterator* Stack::createIterator()
{
    return new StackIterator(this);
}
 
//------------------------------------------------------------------
// IteratorPtr 클래스
class IteratorPtr
{
public:
    IteratorPtr(Iterator* it) : pIter(it) {}
    ~IteratorPtr() { delete pIter; }
 
    Iterator* operator-> () { return pIter; }
    Iterator& operator* () { return *pIter; }
 
protected:
    IteratorPtr(const IteratorPtr& rhs);
    IteratorPtr& operator=(const IteratorPtr& rhs);
 
private:
    Iterator* pIter;
};
 
void PrintData(IteratorPtr& it)
{
    cout << "---------< Print Stack >-----------" << endl;
    for (it->first(); !it->isDone(); it->next())
        cout << it->GetItem()->data << endl;
    cout << "-----------------------------------" << endl;
}
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    Element a("a"), b("b"), c("c"), d("d"), e("e"), f("f"), g("g"), h("h"), i("i"), j("j"), k("k");
 
    Stack stack;
    stack.push(&a);
    stack.push(&b);
    stack.push(&c);
    stack.push(&d);
    stack.push(&e);
    stack.push(&f);
    stack.push(&g);
    stack.push(&h);
    stack.push(&i);
    stack.push(&j);
    stack.push(&k);
    
    IteratorPtr it((StackIterator*)stack.createIterator());
    PrintData(it);
 
    Element *p1 = stack.pop();
    Element *p2 = stack.pop();
 
    cout << "pop 1: " << p1->data << endl;
    cout << "pop 2: " << p2->data << endl;
 
    PrintData(it);
 
    return 0;
}


예제 결과)