[Design Pattern] 행동 패턴 9. 이터레이터 (Iterator)
Table of Contents
이터레이터 (Iterator) #
- 내부 세부구조를 노출하지 않고, 어떤 집합 객체에 속한 요소들을 순차적으로 접근할 수 있는 방법을 제공한다.
개념적인 예시 #
// 이터레이터
abstract class Iterator : IEnumerator
{
object IEnumerator.Current => Current();
public abstract int Key();
public abstract object Current();
public abstract bool MoveNext();
public abstract void Reset();
}
class AlphabeticalOrderIterator : Iterator
{
// 해당 컬렉션
private WordsCollection _collection;
// 현재 위치
private int _position = -1;
private bool _reverse = false;
public AlphabeticalOrderIterator(WordsCollection collection, bool reverse = false)
{
this._collection = collection;
this._reverse = reverse;
if (reverse)
{
this._position = collection.getItems().Count;
}
}
public override object Current()
{
return this._collection.getItems()[_position];
}
public override int Key()
{
return this._position;
}
public override bool MoveNext()
{
int updatedPosition = this._position + (this._reverse ? -1 : 1);
if (updatedPosition >= 0 && updatedPosition < this._collection.getItems().Count)
{
this._position = updatedPosition;
return true;
}
else
{
return false;
}
}
public override void Reset()
{
this._position = this._reverse ? this._collection.getItems().Count - 1 : 0;
}
}
// 이터레이터로 순회할 컬렉션
abstract class IteratorAggregate : IEnumerable
{
public abstract IEnumerator GetEnumerator();
}
class WordsCollection : IteratorAggregate
{
List<string> _collection = new List<string>();
bool _direction = false;
public void ReverseDirection()
{
_direction = !_direction;
}
public List<string> getItems()
{
return _collection;
}
public void AddItem(string item)
{
this._collection.Add(item);
}
public override IEnumerator GetEnumerator()
{
// 이터레이터를 생성한다. (팩토리 메서드)
return new AlphabeticalOrderIterator(this, _direction);
}
}
class Program
{
static void Main(string[] args)
{
// 컬렉션
var collection = new WordsCollection();
collection.AddItem("First");
collection.AddItem("Second");
collection.AddItem("Third");
// Straight traversal
foreach (var element in collection)
{
Console.WriteLine(element);
}
// Reverse traversal
collection.ReverseDirection();
foreach (var element in collection)
{
Console.WriteLine(element);
}
}
}