---
tags: Design Pattern
---
# Iterator
Iterator 可以用將尋訪的邏輯從容器中拿出來管理;讓容器專心在其他重要的事情上,保持職責的單一。要開始巡訪時,就會使用該容器的某一個公開介面 (public interface)來取得在其中的 Iterator,再開始進行操作。
Iterator can be managed by taking the search logic out of the container; let the container concentrate on other important things, and keep the responsibility single. When you want to start a tour, you will use one of the container's public interfaces to get the Iterator in it, and then start operating.
<font color="#f00">advantage:</font>
1. could delete while traversing
<font color="#f00">disadvantage:</font>
1. only traverse from the beginning
---
### Iterator vs for
1. iterator
迭代器遍歷方式, 適用於連續記憶體儲存方式,比如陣列、 ArrayList。 缺點是隻能從頭開始遍歷, 優點是可以邊遍歷邊刪除。
2. for list.size方式遍歷
這種方式遍歷比較靈活,可以指定位置開始遍歷。效能最高,但是使用不太優雅,每次都需要在應用程式中手動強轉和額外的獲得list.size,這樣就會導致產生額外的程式碼。
基於for方式的遍歷,還有一個缺點就是遍歷過程中不允許刪除元素,否則會拋ConcurrentModificationException。
---
1. iterator
The iterator traversal method is suitable for continuous memory storage methods, such as arrays and ArrayList. The disadvantage is that it can only be traversed from the beginning, and the advantage is that it can be deleted while traversing.
2. for list.size traversal
This way of traversal is more flexible, and you can specify a position to start traversal. The performance is the highest, but the use is not very elegant. It needs to be manually forced in the application and additionally obtain the list.size each time, which will lead to additional code.
Another disadvantage of for-based traversal is that elements are not allowed to be deleted during the traversal process, otherwise ConcurrentModificationException will be thrown.
---
iterator.h
```cpp=
#pragma once
class Shape;
class Iterator {
public:
virtual ~Iterator(){}
virtual void first() = 0;
virtual Shape* currentItem() const = 0;
virtual void next() = 0;
virtual bool isDone() const = 0;
};
```
null_iterator.h
For other components that don't need to use iterator
```cpp=
#pragma once
#include "../shape.h"
#include "./iterator.h"
class NullIterator : public Iterator {
public:
void first() override { throw("method not allowed"); }
Shape* currentItem() const override { throw("method not allowed"); }
void next() override { throw("method not allowed"); }
bool isDone() const override { return true; }
};
```
---
compound_iterator.h
```cpp=
#pragma once
#include "../shape.h"
#include "./iterator.h"
#include <string>
#include <list>
// define a template class `ForwardIterator`
template <class ForwardIterator>
class CompoundIterator : public Iterator
{
public:
CompoundIterator(ForwardIterator begin, ForwardIterator end) : _begin(begin), _end(end)
{
// initialize
first();
}
void first() override { _current = _begin; }
Shape *currentItem() const override
{
if (isDone())
{
throw("is done");
return NULL;
}
else
{
return *_current;
}
}
void next() override
{
if (isDone())
{
throw("is done");
}
else
{
++_current;
}
}
bool isDone() const override { return _current == _end; }
private:
ForwardIterator _begin, _end, _current;
};
```
---
circle use null_iterator.h
```cpp=
Iterator* createIterator() override { return new NullIterator(); }
```
---
compoundShape use compound_iterator.h
```cpp=
Iterator *createIterator() override { return new CompoundIterator<std::list<Shape *>::iterator>(_shapes.begin(), _shapes.end()); }
void addShape(Shape *shape) override { _shapes.push_back(shape); }
void deleteShape(Shape *shape) override
{
if (!_shapes.size())
{
throw "empty";
}
else
{
_shapes.remove(shape);
}
}
```
---
You can manipulate and know the current currentItem() through Iterator, or make modifications. For detailed tests, see ut_compound_shape.h and ut_iterator.h.
The relevant code is in: https://github.com/andy091045/Design-Pattern/tree/main/posd2021f_110598068_hw03
reference: https://www.796t.com/content/1550063720.html