반복자 패턴 (Iterator Pattern)
Gof Design Pattern2014. 2. 4. 01:44
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; } |
예제 결과)
'Gof Design Pattern' 카테고리의 다른 글
방문자 패턴 (Visitor Pattern) (0) | 2014.02.04 |
---|---|
중재자 패턴 (Mediator Pattern) (0) | 2014.02.04 |
책임 연쇄 패턴 (Chain of Responsibility) (0) | 2014.02.03 |
커멘트 패턴 (Command Pattern) (2) | 2014.02.03 |
디자인 패턴 관계도 (Design Pattern Relationships) (0) | 2014.02.01 |