[C#][デザインパターン] Iteratorパターン

スポンサーリンク

オブジェクトAとオブジェクトBがあり、オブジェクトBが持つ配列をオブジェクトAの中でforを使用して取り出すことを考えてみましょう。

オブジェクトBの配列をオブジェクトAから操作する

この場合、オブジェクトAは以下のことを知っている必要があります。

  • オブジェクトBが持つデータの構造が配列であること
  • 配列の名前や先頭の要素番号や末尾の要素番号

もし、オブジェクトAの中で、読み取る配列のインデックス番号を間違えてしまったらエラーになってしまいます。

また、オブジェクトBのデータが配列からリストやスタックといったデータ構造に変更されてしまった場合には、オブジェクトAを書き換える必要が生じます。

この問題を解決するためにIteratorパターンを使用します。

Iteratorパターンは、

  • オブジェクトが持つデータの構造は非公開にする
  • オブジェクトがデータを持っているかどうかをhasNextメソッドで表す。
  • オブジェクトの取り出しはnextメソッドを介して行う

という特徴があります。

最初にhasNextメソッドとnextメソッドを持つインターフェースを定義します。

C#の例

interface IIterator
{
    bool hasNext();
    string next();
}

次に上記で作成したインターフェースを持つConcreatAggregateクラスを定義します。

class ConcreatAggregate : IIterator
{
    private List<string> aggregate = new List<string>();
    private int _nextIndex = 0;

    /// <summary>
    /// 要素の追加
    /// </summary>
    /// <param name="item"></param>
    public void addItem(string item)
    {
        aggregate.Add(item);
    }

    /// <summary>
    /// 次のアイテムがある場合はtrue
    /// </summary>
    /// <returns></returns>
    public bool hasNext()
    {
        return this._nextIndex < this.length;
    }

    /// <summary>
    /// 次のアイテムを取得
    /// </summary>
    /// <returns></returns>
    public string next()
    {
        return aggregate[this._nextIndex++];
    }

    /// <summary>
    /// 要素数
    /// </summary>
    public int length 
    { 
        get
        {
            return this.aggregate.Count;
        }

    }
}

以上でIteratorパターンの実装は完了です。

あとは実際にConcreateAggregateクラスを使用してみます。

while文の条件で hasNextメソッドを使用し、次のアイテムがある間はループをします。

このようにIteratorパターンを使用すると、要素数がいくつあるかを気にすることなく順番に取り出すことが可能です。

static void Main(string[] args)
{
    ConcreatAggregate agr = new ConcreatAggregate();
    agr.addItem("test1");
    agr.addItem("test2");
    agr.addItem("test3");

    // 次のアイテムがある間はループする
    while (agr.hasNext())
    {
        // アイテムを取り出して表示
        Console.WriteLine(agr.next());
    }
}
Please follow and like us:

コメント

タイトルとURLをコピーしました