【デザインパターン】イテレータパターンとは?データ構造を柔軟に扱う設計手法を解説

イテレータパターンは、コレクション(配列やリストなど)の内部構造を隠蔽しつつ、要素を順番に走査する方法を提供するデザインパターンです。

C#を例に具体的な実装を紹介しますが、JavaやPythonなど他の言語でも応用できます。このパターンを使うことで、異なるデータ構造に対して統一的なアクセス手法を確立し、柔軟な設計が可能になります。

目次

受講者数No.1!初心者からプロへ導く信頼のスクール

    短期間で習得可能!未経験から実践力を磨く充実のプログラム

    今なら無料相談でAmazonギフトカードがもらえる!

    イテレータパターンとは?

    イテレータパターン(Iterator Pattern)は、オブジェクトの集合(コレクション)の要素に順番にアクセスするための設計手法です。
    通常、配列やリストなどのデータ構造を直接操作すると、その内部実装に依存してしまいます。しかし、イテレータパターンを使えば、データ構造の詳細を隠しながら、統一的な方法でデータを扱えます。

    イテレータパターンのメリット

    イテレータパターンを採用することで、以下のようなメリットがあります。

    • データ構造を意識せずに要素を取得できる
    • 異なるコレクション型を統一的に扱える
    • 要素の取得方法を柔軟にカスタマイズ可能
    • 拡張性が向上し、コードの可読性が高まる

    C#でのイテレータパターンの実装

    C#では、IEnumerable<T> インターフェースを利用してイテレータパターンを簡単に実装できます。
    以下では、独自のコレクションクラスを作成し、カスタムイテレータを実装する方法を紹介します。

    1. コレクションを表すクラス

    まず、IEnumerable<T> を実装したカスタムコレクションクラスを作成します。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    
    // カスタムコレクション
    class CustomCollection<T> : IEnumerable<T>
    {
        private List<T> _items = new List<T>();
    
        // 要素を追加するメソッド
        public void Add(T item) => _items.Add(item);
    
        // イテレータを取得
        public IEnumerator<T> GetEnumerator() => new CustomIterator<T>(_items);
    
        // 非ジェネリック版のGetEnumerator(IEnumerableの実装)
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
    

    IEnumerable<T> を実装すると、C#の foreach を使って要素を簡単にループできます。

    2. イテレータを表すクラス

    次に、IEnumerator<T> を実装して、カスタムイテレータを作成します。

    // カスタムイテレータ
    class CustomIterator<T> : IEnumerator<T>
    {
        private List<T> _items;
        private int _position = -1;
    
        public CustomIterator(List<T> items) => _items = items;
    
        // 現在の要素を取得
        public T Current => _items[_position];
    
        object IEnumerator.Current => Current;
    
        // 次の要素へ移動
        public bool MoveNext()
        {
            if (_position + 1 < _items.Count)
            {
                _position++;
                return true;
            }
            return false;
        }
    
        // イテレータをリセット
        public void Reset() => _position = -1;
    
        // リソースの解放(今回は特に不要)
        public void Dispose() { }
    }
    

    MoveNext() で次の要素に進み、Current で現在の要素を取得します。


    3. 実際の使用例

    作成したカスタムコレクションを使って、foreach で要素を取得してみます。

    class Program
    {
        static void Main()
        {
            CustomCollection<string> collection = new CustomCollection<string>();
    
            collection.Add("Apple");
            collection.Add("Banana");
            collection.Add("Cherry");
    
            foreach (var item in collection)  // イテレータが内部的に動作
            {
                Console.WriteLine(item);
            }
        }
    }
    
    Apple
    Banana
    Cherry
    

    4. C#のyield return を使った簡単な実装

    C#では、IEnumerator<T> を直接実装しなくても、yield return を使うことで簡単にイテレータを作成できます。

    using System;
    using System.Collections.Generic;
    
    // カスタムコレクション
    class CustomCollection<T>
    {
        private List<T> _items = new List<T>();
    
        public void Add(T item) => _items.Add(item);
    
        // `yield return` を使った簡単なイテレータ
        public IEnumerable<T> GetItems()
        {
            foreach (var item in _items)
            {
                yield return item;  // 要素を順番に返す
            }
        }
    }
    
    class Program
    {
        static void Main()
        {
            CustomCollection<string> collection = new CustomCollection<string>();
    
            collection.Add("Dog");
            collection.Add("Cat");
            collection.Add("Rabbit");
    
            foreach (var item in collection.GetItems())
            {
                Console.WriteLine(item);
            }
        }
    }
    
    Dog
    Cat
    Rabbit
    

    yield return を使うと、IEnumerator<T> の実装が不要になり、シンプルなコードでイテレータを実現できます。

    • IEnumerable<T> を実装すると、foreach でループできるようになる
    • IEnumerator<T> を使うと、カスタムイテレータを作成できる
    • yield return を使えば、簡単にイテレータを作れる
    • データ構造を意識せずに統一的な方法で要素を走査できる

    イテレータパターンを使うことで、コードの再利用性が向上し、異なるデータ構造を一貫した方法で扱うことができます!

    イテレータパターンを使うべきケース

    イテレータパターンは、以下のような状況で特に有効です。

    • 異なるデータ構造(リスト、配列、ツリー、グラフなど)を統一的に走査したいとき
    • データ構造の内部実装を隠蔽し、安全にアクセスさせたいとき
    • 独自のルールで要素の取得順序やフィルタリングをしたいとき
    • foreach などの構文を自作のコレクションで利用したいとき
    • 順番にアクセスする処理を統一し、コードの可読性と拡張性を向上させたいとき

    このパターンを使うことで、データ構造に依存しない柔軟な設計が可能になります。

    まとめ

    • イテレータパターンは、データ構造を意識せずに要素を順番に走査するためのデザインパターン。
    • IEnumerable<T> を実装すると、foreach で統一的にデータを扱える。
    • IEnumerator<T> を使えば、カスタムイテレータを作成できる。
    • yield return を活用すると、簡潔なコードでイテレータを実装可能。
    • 異なるデータ構造(リスト、ツリー、グラフなど)でも、統一的なアクセスが可能になり、コードの可読性・拡張性が向上する。

    イテレータパターンを活用すると、異なるデータ構造を統一的に扱え、コードの柔軟性や再利用性が向上します。特に、foreach を使えるようにしたり、データアクセスをカプセル化することで、保守性の高いプログラムを実現できます。

    C#では IEnumerable<T>yield return を活用することで、簡単にイテレータを実装できるため、ぜひ実践してみてください!

    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!
    目次