デザインパターン入門_メモ_Iterator

# Javade学ぶデザインパターン入門

結城浩「Javaで学ぶデザインパターン入門」をC#で勉強

## Iterator パターン

今回はIteratorパターン

### 実装

```

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternLearn.IteratorLearn
{
    /// <summary>
    /// Mainはテキスト通り
    /// </summary>
    class Test
    {
        public static void Main(string[] args)
        {
            BookShelf bookShelf = new BookShelf(4);
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門1"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門2"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門3"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門4"));
            ITerator it = bookShelf.iTerator();
            while (it.HasNext())
            {
                Book book = (Book)it.Next();
                Console.WriteLine(book.Name);
            }
            Console.Read();
        }
    }

    public interface Aggrregate
    {
        ITerator iTerator();
    }

    /// <summary>
    /// 要素の数え上げ、ループ変数のような役割
    /// </summary>
    public interface ITerator
    {
        bool HasNext();
        object Next();
    }

    public class BookShelfIterator : ITerator
    {
        private BookShelf bookShelf;
        private int index;

        public BookShelfIterator(BookShelf bookShelf)
        {
            this.bookShelf = bookShelf;
        }

        public bool HasNext()
        {
            return bookShelf.GetLength() >= (index + 1) ? true : false;  
        }

        public object Next()
		{
			if (HasNext())
			{
				this.index = index + 1;
				return bookShelf.GetBookAt(index - 1);
			} else
			{
				return null;
			}
		}
    }

    /// <summary>
    /// Aggregateを実装すること
    /// → 内部でIteratorメソッドを実装する必要がある。
    /// </summary>
    public class BookShelf : Aggrregate
    {
        private Book[] books;
        private int last;

        public BookShelf()
        {
            this.books = new Book[] { };
            this.last = 0;
        }

        /// <summary>
        /// Mainを見た後に追加した
        /// </summary>
        /// <param name="last"></param>
        public BookShelf(int itemNum)
        {
            this.books = new Book[itemNum];
            this.last = 0;
        }

        public Book GetBookAt(int index)
        {
            return books[index];
        }

        public void AppendBook(Book book)
        {
            books[last] = book;
            last = last + 1;
        }

        public int GetLength()
        {
            return last;
        }

        /// <summary>
        /// ここが重要
        /// Iteratorメソッドを実装する際に、
        /// Iteratorインターフェイスを実装しているクラスのコンストラクタを
        /// 呼び出してる
        /// → Iteratorの対象を切り替えるのが簡単
        /// </summary>
        /// <returns></returns>
        public ITerator iTerator()
        {
            return new BookShelfIterator(this);
        }
    }

    public class Book
    {
        public string Name { get; set; }

        public Book(string name)
        {
            this.Name = name;
        }
    }
}



```

## 重要な考え方(抜粋)

Iteratorを使うことで、実装とは切り離して、数え上げを行うことができる。
→ BookShelfをそのまま用いず、BookShelf中のIterator(BookSshelfIterator)を使用
　 BookShelfの中身は、Iteratorが知っていればよい。
   そのため、BookShelfの実装を変更しても、Main関数などそれを呼び出す側の実装を変更せずにすむ。

## 練習問題1-1

上記のBookShelfクラスでは上限を超えて本を収納することができない。
上限を超えても本を格納できるように変更せよ。

### 実装

```
　　/// <summary>
    /// Aggregateを実装すること
    /// → 内部でIteratorメソッドを実装する必要がある。
    /// </summary>
    public class BookShelf : Aggrregate
    {
        private List<Book> books;
        private int last;

        public BookShelf()
        {
            this.books = new List<Book>();
            this.last = 0;
        }

        /// <summary>
        /// Mainを見た後に追加した
        /// </summary>
        /// <param name="last"></param>
        public BookShelf(int itemNum)
        {
            this.books = new List<Book>(itemNum);
            this.last = 0;
        }

        public Book GetBookAt(int index)
        {
            return books[index];
        }

        public void AppendBook(Book book)
        {
            books.Add(book);
            last = last + 1;
        }

        public int GetLength()
        {
            return last;
        }

        /// <summary>
        /// ここが重要
        /// Iteratorメソッドを実装する際に、
        /// Iteratorインターフェイスを実装しているクラスのコンストラクタを
        /// 呼び出してる
        /// → Iteratorの対象を切り替えるのが簡単
        /// </summary>
        /// <returns></returns>
        public ITerator iTerator()
        {
            return new BookShelfIterator(this);
        }
    }

```