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);
}
}