18.4 구현
반복자 패턴에 대한 예제 프로그램을 구현하는 순서는 Collection, Iterator, Arr과 ArrIterator, Tracer순으로 하겠습니다.
18.4.1 IContainer
IContainer에서는 일반적으로 컬렉션에 필요한 메서드에 대한 구현 약속만 하면 되겠죠. 여기에서는 보관하는 메서드와 삭제, 전체 해제, 현재 보관된 수를 얻어오는 속성에 대한 약속을 하겠습니다.
▶ IContainer.cs
using System; namespace Iterator { interface IContainer { bool Add(Object elem); void Remove(Object elem); void Clear(); int Count { get; } } }
18.4.2 IIterator
IIterator에서는 컬렉션을 순회하기 시작하기 전에 사용하는 메서드와 다음 위치로 변경하는 메서드, 현재 위치의 보관된 것을 얻어오는 속성을 제공하도록 약속하겠습니다. 이와 같은 추상화 작업은 일관된 방법으로 사용할 수 있게 함을 여러분은 잘 알고 있을 것입니다.
▶ IIterator.cs
using System; namespace Iterator { interface IIterator { void Begin(); bool MoveNext(); Object Current { get; } } }
18.4.3 Arr과 ArrIterator
이제 인터페이스 IContainer를 구현 약속하는 Arr 클래스를 정의하고 Arr 클래스 형식 개체를 반복적으로 순회하면서 보관된 개체를 탐방할 수 있는 ArrIterator를 정의해 봅시다. 물론, ArrIterator 클래스도 인터페이스 IIterator를 구현 약속해야겠지요.
여기에서는 Arr 클래스의 Add, Remove, Clear메서드와 Count 속성의 구체적인 코드에 대한 설명을 생략하겠습니다. 이 책을 보고 있으신 여러분들은 이미 자료구조에 대한 선 지식이 있을 것이며 그렇지 않다고 하더라도 충분히 분석할 수 있을 것이라 믿습니다.
C#에서는 모든 컬렉션이 IEnumerable, IEnumerator를 구현 약속하게 설계되어 있습니다. 반면 여기에서는 Arr 컬렉션내에 IIterator를 구현 약속한 ArrIterator 클래스를 구현하는 형태로 설계할 것입니다. 여러분들은 어떠한 구조가 어떠한 장점과 단점을 갖는지 고민해 보시기 바랍니다.
▶ Arr.cs
using System; namespace Iterator { class Arr:IContainer { Object[] buffer; readonly int max_element; public Arr(int max_element) { this.max_element = max_element; buffer = new Object[max_element]; } #region IContainer 멤버 public bool Add(object elem) { if(Count < max_element) { buffer[Count] = elem; Count++; return true; } return false; } public void Remove(object elem) { int index = Find(elem); if (index == -1) { return; } Count--; for(int i =index; i<Count;i++) { buffer[i] = buffer[i+1]; } } public void Clear() { Count=0; } public int Count { get; private set; } #endregion public class ArrIterator:IIterator { Object[] buffer; int bsize; int index; public ArrIterator(Object[] buffer, int bsize) { this.buffer = buffer; this.bsize = bsize; } #region IIterator 멤버 void IIterator.Begin() { index = -1; } bool IIterator.MoveNext() { index++; if (index < bsize) { return true; } return false; } object IIterator.Current { get { return buffer[index]; } } #endregion } public IIterator MakeIterator() { return new ArrIterator(buffer, Count); } int Find(Object elem) { int index=0; for( index=0 ; index < Count ; index++) { if(buffer[index] == elem) { return index; } } return -1; } } }
18.4.4 Tracer
Tracer에서는 정수형을 보관하는 Arr 컬렉션 개체에 여러 정수를 보관한 후에 ArrIterator 개체를 얻어와서 정상적으로 순회할 수 있는지를 확인하는 정적 메서드를 만드는 것으로 하였습니다.
▶ Tracer.cs
using System; namespace Iterator { class Tracer { public static void DoIt() { Arr arr = new Arr(10); arr.Add(3); arr.Add(6); arr.Add(7); IIterator iter = arr.MakeIterator(); iter.Begin(); while (iter.MoveNext()) { Console.WriteLine(iter.Current.ToString()); } } } }
▶ Program.cs
using System; namespace Iterator { class Program { static void Main(string[] args) { Tracer.DoIt(); } } }
▶ 실행 결과
6 7