Iteratorパターン
データ集合から要素を順にアクセスする方法を提供する
プログラミングにおいて、あるデータの集合から各データ要素を順にとりだして利用したいことがよくあります。こういった時に利用できるのがIteratorパターンです。もう少し正確に説明すると、Iteratorパターンは「データの集合を表現するオブジェクト」から、「集合の各要素へ順番にアクセスするアルゴリズム」を切り離すことを目的とするデザインパターンといえます。
Iteratorパターン は、オブジェクトの持つデータ構造を非公開にして、次の2つのメソッドだけを公開するというものです(メソッド名は何でも良いですが、とりあえず Java の Iterator インタフェースに合わせました)。
②そのページを開く
②ひとつ取り出す
まだあるでしょ?
②ひとつ白状する
| 機能 | メソッド |
|---|---|
| 次のデータがあるかどうか① | hasNext() |
| 次のデータを取得し、その次に進む② | next() |
① のメソッドは、まだ取得されていないデータが残っていれば true を返し、残ってないなら false を返します。② は、順番にデータを取得して返します。① のメソッドで「データありますか?」と質問し、答えが true なら ② のメソッドで「データください」と要求するわけです。
では、どうしてIteratorパターンという面倒なものを考える必要があるのでしょう。配列だったら、for 文でくるくる回せばいいじゃないか、という疑問がわいてきます。
Iteratorパターンを使う、その大きな理由は、実装とは切り離して数え上げを行うことができるからです。Iteratorパターンでは、① と ② しか呼び出されません。つまり、実際のデータが配列なのか、リストなのか、スタックなのかといった実装には依存しないということになるからです。実際のデータが配列からリストに変更になっても、ユーザプログラムの ① と ② を使用しているところは変更しなくてもすみます。
Iteratorは、全体のサイズが把握できないストリームや、一括でデータを返してくるのではなく順次返してくるデータに対して有効です。
例題
本が4冊入っている本棚があります。本棚に入っている本の名前を表示してください。
本は Book クラス、本棚は BookShelf クラスとして定義されています。
BBBBB
CCCCC
DDDDD
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.java public class BookShelf {
private Book[] books;
private int last = 0;
public BookShelf(int maxsize) {
this.books = new Book[maxsize];
}
public Book getBookAt(int index) {
return books[index];
}
public void appendBook(Book book) {
this.books[last++] = book;
}
public int getCount() {
return last;
}
}
Main.java public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
int i = 0;
while (i < bookShelf.getCount()) {
Book book = bookShelf.getBookAt(i++);
System.out.println(book.getName());
}
}
}
|
Iteratorパターンを使用した例 BookShelf.java public class BookShelf {
private Book[] books;
private int last = 0;
public BookShelf(int maxsize) {
this.books = new Book[maxsize];
}
public Book getBookAt(int index) {
return books[index];
}
public void appendBook(Book book) {
this.books[last++] = book;
}
public int getCount() {
return last;
}
public IIterator<Book> iterator() {
return new BookShelfIterator(this);
}
}
IIterator.java public interface IIterator<T> {
public abstract boolean hasNext();
public abstract T next();
}
BookShelfIterator.java public class BookShelfIterator implements IIterator<Book> {
private BookShelf bookShelf;
private int index;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
public boolean hasNext() {
return (index < bookShelf.getCount());
}
public Book next() {
return bookShelf.getBookAt(index++);
}
}
Main.java public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
IIterator<Book> it = bookShelf.iterator();
while (it.hasNext()) {
Book book = it.next();
System.out.println(book.getName());
}
}
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています(java.util.Iterator もありますが、ここではあえて使用せず、IIterator を自作しています)。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 bookShelf.h #include "book.h"
class BookShelf
{
private:
Book* books;
int last;
public:
BookShelf(void);
BookShelf(int);
virtual ~BookShelf(void);
Book getBookAt(int);
void appendBook(Book&);
int getCount(void);
};
bookShelf.cpp #include "bookShelf.h"
BookShelf::BookShelf(void) {}
BookShelf::BookShelf(int maxsize) : books(new Book[maxsize]), last(0) {}
BookShelf::~BookShelf(void)
{
delete[] books;
}
Book BookShelf::getBookAt(int index)
{
return books[index];
}
void BookShelf::appendBook(Book& book)
{
books[last++] = book;
}
int BookShelf::getCount(void)
{
return last;
}
main.cpp #include <iostream>
using namespace std;
#include "bookShelf.h"
int main()
{
BookShelf bs(10);
bs.appendBook(Book("AAAAA"));
bs.appendBook(Book("BBBBB"));
bs.appendBook(Book("CCCCC"));
bs.appendBook(Book("DDDDD"));
int i = 0;
while (i < bs.getCount())
{
Book b = (Book)bs.getBookAt(i++);
cout << b.getName() << endl;
}
return 0;
}
|
Iteratorパターンを使用した例 bookShelf.h #include "book.h"
class BookShelfIterator;
class BookShelf
{
private:
Book* books;
int last;
public:
bookShelf(int);
virtual ~bookShelf(void);
Book& getBookAt(int);
void appendBook(Book&);
int getCount(void);
BookShelfIterator* iterator(void);
}; bookShelf.cpp #include "bookShelfIterator.h"
#include "bookShelf.h"
BookShelf::BookShelf(int maxsize) : books(new Book[maxsize]), last(0) {}
Book& BookShelf::getBookAt(int index)
{
return books[index];
}
BookShelf::~BookShelf(void)
{
delete[] books;
}
void BookShelf::appendBook(Book& book)
{
books[last++] = book;
}
int BookShelf::getCount(void) {
return last;
}
BookShelfIterator BookShelf::iterator(void)
{
return new BookShelfIterator(this);
}
iiterator.h template <class T>
class Iterator
{
public:
virtual bool hasNext() = 0;
virtual T next() = 0;
}; iiterator.cpp #include "iIterator.h"
bookShelfIterator.h #include "book.h"
#include "iiterator.h"
class BookShelf;
class BookShelfIterator : public IIterator<Book>
{
private:
BookShelf* bookShelf;
unsigned int index = 0;
public:
BookShelfIterator(BookShelf*);
virtual ~BookShelfIterator(void);
bool hasNext(void);
Book next(void);
}; bookShelfIterator.cpp #include "bookShelf.h"
#include "bookShelfIterator.h"
bookShelfIterator::bookShelfIterator(BookShelf* bookShelf) {
this->bookShelf = bookShelf;
}
BookShelfIterator::~BookShelfIterator(void) {}
bool BookShelfIterator::hasNext(void) {
return index < bookShelf->getCount();
}
Book BookShelfIterator::next(void) {
return bookShelf->getBookAt(index++);
}
main.cpp #include <iostream>
using namespace std;
#include "bookShelf.h"
#include "iterator.h"
int main()
{
BookShelf bookShelf(10);
bookShelf.appendBook(Book("AAAAA")));
bookShelf.appendBook(Book("BBBBB")));
bookShelf.appendBook(Book("CCCCC")));
bookShelf.appendBook(Book("DDDDD")));
BookShelfIterator* it = bookShelf.iterator();
while (it->hasNext()) {
Book book = it->next();
cout << book.getName() << endl;
}
return 0;
} |
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 なお、C++ には、インタフェースの異なる std::iteratorクラスもありますが、C++17から非推奨となったようなので、ここでは使用しませんでした。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.cs
class BookShelf
{
private Book[] books;
private int last = 0;
public BookShelf(int maxSize)
{
this.books = new Book[maxSize];
}
public Book GetBookAt(int index)
{
return books[index];
}
public void AppendBook(Book book)
{
this.books[last++] = book;
}
public int GetCount()
{
return last;
}
}
Program.cs class Program
{
static void Main(string[] args)
{
BookShelf bookShelf = new BookShelf(5);
bookShelf.AppendBook(new Book("AAAAA"));
bookShelf.AppendBook(new Book("BBBBB"));
bookShelf.AppendBook(new Book("CCCCC"));
bookShelf.AppendBook(new Book("DDDDD"));
int i = 0;
while (i < bookShelf.GetCount())
{
Book book = bookShelf.GetBookAt(i++);
Console.WriteLine(book.GetName());
}
}
} |
Iteratorパターンを使用した例 BookShelf.cs class BookShelf
{
private Book[] books;
private int last = 0;
public BookShelf(int maxSize)
{
this.books = new Book[maxSize];
}
public Book GetBookAt(int index)
{
return books[index];
}
public void AppendBook(Book book)
{
this.books[last++] = book;
}
public int GetCount()
{
return last;
}
public BookShelfIterator Itarator()
{
return new BookShelfIterator(this);
}
}
IIterator.cs interface IIterator<T>
{
bool HasNext();
T Next();
}
BookShelfIterator.cs public class BookShelfIterator : IIterator<Book>
{
private BookShelf bookShelf;
private int index;
public BookShelfIterator(BookShelf bookShelf)
{
this.bookShelf = bookShelf;
index = 0;
}
public bool HasNext
{
return index < bookShelf.GetCount();
}
public Book Next()
{
return bookShelf.GetBookAt(index++);
}
}
Program.cs class Program
{
static void Main(string[] args)
{
BookShelf bookShelf = new BookShelf(5);
bookShelf.AppendBook(new Book("AAAAA"));
bookShelf.AppendBook(new Book("BBBBB"));
bookShelf.AppendBook(new Book("CCCCC"));
bookShelf.AppendBook(new Book("DDDDD"));
BookShelfIterator it = bookShelf.Itarator();
while(it.HasNext())
{
Book book = it.Next();
Console.WriteLine(book.GetName());
}
}
} |
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 なお、C++ には、IEnumerator インタフェースもありますが、メソッドが MoveNext() や Current() なのでここでは使用しませんでした。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.vb Public Class BookShelf
Private books() As Book
Private last As Integer = 0
Public Sub New(ByVal maxSize As Integer)
Me.books = New Book(maxSize) {}
End Sub
Public Function GetBookAt(ByVal index As Integer) As Book
Return books(index)
End Function
Public Sub AppendBook(ByVal book As Book)
Me.books(last) = book
last += 1
End Sub
Public Function GetCount() As Integer
Return last
End Function
End Class
Main.vb Module Main
Sub Main()
Dim bookShelf As BookShelf = New BookShelf(3)
bookShelf.AppendBook(New Book("AAAAA"))
bookShelf.AppendBook(New Book("BBBBB"))
bookShelf.AppendBook(New Book("CCCCC"))
bookShelf.AppendBook(New Book("DDDDD"))
Dim i As Integer = 0
While (i < bookShelf.GetCount())
Dim book As Book = bookShelf.GetBookAt(i)
i += 1
Console.WriteLine(book.GetName())
End While
End Sub
End Module |
Iteratorパターンを使用した例 BookShelf.vb Public Class BookShelf
Private books() As Book
Private last As Integer = 0
Public Sub New(ByVal maxSize As Integer)
Me.books = New Book(maxSize) {}
End Sub
Public Function GetBookAt(ByVal index As Integer) As Book
Return books(index)
End Function
Public Sub AppendBook(ByVal book As Book)
Me.books(last) = book
last += 1
End Sub
Public Function GetCount() As Integer
Return last
End Function
Public Function Iterator() As BookShelfIterator
Return New BookShelfIterator(Me)
End Function
End Class
IIterator.vb Public Interface IIterator(Of T)
Function HasNext() As Boolean
Function [Next]() As T
End Interface
BookShelfIterator.vb Public Class BookShelfIterator
Implements IIterator(Of Book)
Private bookShelf As BookShelf
Private index As Integer
Public Sub New(ByVal bookShelf As BookShelf)
Me.bookShelf = bookShelf
index = 0
End Sub
Public Function HasNext() As Boolean Implements IIterator(Of Book).HasNext
Return index < bookShelf.GetCount()
End Function
Public Function [Next]() As Book Implements IIterator(Of Book).[Next]
index += 1
Return bookShelf.GetBookAt(index - 1)
End Function
End Class
Main.vb Module Main
Sub Main()
Dim bookShelf As BookShelf = New BookShelf(3)
bookShelf.AppendBook(New Book("AAAAA"))
bookShelf.AppendBook(New Book("BBBBB"))
bookShelf.AppendBook(New Book("CCCCC"))
bookShelf.AppendBook(New Book("DDDDD"))
Dim it As BookShelfIterator = bookShelf.Iterator()
While (it.HasNext())
Dim book As Book = it.Next()
Console.WriteLine(book.GetName())
End While
End Sub
End Module |
|
main の繰り返しの部分で BookShelf の GetBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは GetBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 なお、Visual Basic には、IEnumerator インタフェースもありますが、メソッドが MoveNext() や Current() なのでここでは使用しませんでした。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.java module.exports = class BookShelf {
constructor(maxsize) {
this.books = new Array[maxsize];
this.last = 0;
}
getBookAt(index) {
return this.books[index];
}
appendBook(book) {
this.books[this.last++] = book;
}
getCount() { return this.last; }
}
Main.js const BookShelf = require("./BookShelf.js");
const Book = require("./Book.js");
let bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
let i = 0;
while (i < bookShelf.getCount()) {
let book = bookShelf.getBookAt(i++);
process.stdout.write(book.getName() + "\n");
}
|
Iteratorパターンを使用した例 BookShelf.js const BookShelfIterator = require("./BookShelfIterator.js");
module.exports = class BookShelf {
constructor(maxsize) {
this.books = new Array[maxsize];
this.last = 0;
}
getBookAt(index) {
return this.books[index];
}
appendBook(book) {
this.books[this.last++] = book;
}
getCount() { return this.last; }
iterator() {
return new BookShelfIterator(this);
}
}
IIterator.js module.exports = class IIterator {
constructor() {}
hasNext() {
console.log("hasNext メソッドを定義してください。");
}
next() {
console.log("next メソッドを定義してください。");
}
}
BookShelfIterator.js const IIterator = require("./IIterator.js");
module.exports = class BookShelfIterator extends IIterator {
constructor(bookShelf) {
super();
this.bookShelf = bookShelf;
this.index = 0;
}
hasNext() {
return (this.index < this.bookShelf.getCount());
}
next() {
return this.bookShelf.getBookAt(this.index++);
}
}
Main.js const BookShelf = require("./BookShelf.js");
const Book = require("./Book.js");
let bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
let it = bookShelf.iterator();
while (it.hasNext()) {
let book = it.next();
process.stdout.write(book.getName() + "\n");
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.pm package BookShelf {
sub new {
my ($class) = @_;
my $this = { last => 0,
books => []
};
return bless $this, $class;
}
sub getBookAt {
my ($this, $no) = @_;
return $this->{books}[$no];
}
sub appendBook {
my ($this, $book) = @_;
$this->{books}[$this->{last}++] = $book;
}
sub getCount {
my ($this) = @_;
return $this->{last};
}
}
1;
Main.pl use lib qw(./);
use Book;
use BookShelf;
my $bookShelf = new BookShelf(4);
$bookShelf->appendBook(new Book("AAAAA"));
$bookShelf->appendBook(new Book("BBBBB"));
$bookShelf->appendBook(new Book("CCCCC"));
$bookShelf->appendBook(new Book("DDDDD"));
my $i = 0;
while ($i < $bookShelf->getCount()) {
my $book = $bookShelf->getBookAt($i++);
print $book->getName() . "\n";
}
|
Iteratorパターンを使用した例 BookShelf.pm package BookShelf {
use BookShelfIterator;
sub new {
my ($class) = @_;
my $this = { last => 0,
books => []
};
return bless $this, $class;
}
sub getBookAt {
my ($this, $no) = @_;
return $this->{books}[$no];
}
sub appendBook {
my ($this, $book) = @_;
$this->{books}[$this->{last}++] = $book;
}
sub getCount {
my ($this) = @_;
return $this->{last};
}
sub iterator {
my ($this) = @_;
return new BookShelfIterator($this);
}
}
1;
IIterator.pm package IIterator {
sub hasNext {
my ($this) = @_;
print "hasNext メソッドを定義してください。";
}
sub next {
my ($this) = @_;
print "next メソッドを定義してください。";
}
}
1;
BookShelfIterator.pm package BookShelfIterator {
use base qw(IIterator);
sub new {
my ($class, $bookShelf) = @_;
my $this = {
bookShelf => $bookShelf,
index => 0
};
return bless $this, $class;
}
sub hasNext {
my ($this) = @_;
return $this->{index} < $this->{bookShelf}->getCount();
}
sub next {
my ($this) = @_;
return $this->{bookShelf}->getBookAt($this->{index}++);
}
}
1;
Main.pl use lib qw(./);
use Book;
use BookShelf;
my $bookShelf = new BookShelf(4);
$bookShelf->appendBook(new Book("AAAAA"));
$bookShelf->appendBook(new Book("BBBBB"));
$bookShelf->appendBook(new Book("CCCCC"));
$bookShelf->appendBook(new Book("DDDDD"));
my $it = $bookShelf->iterator();
while ($it->hasNext()) {
my $book = $it->next();
print $book->getName() . "\n";
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 では、どのようになっているか見てみましょう。 BookShelf クラスに iterator() メソッド、そして BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.rb require './Book'
class BookShelf
def initialize(maxsize)
@books = Array.new(maxsize)
@last = 0
end
def getBookAt(index)
return @books[index]
end
def appendBook(book)
@books[@last] = book
@last += 1
end
def getCount()
return @last
end
end
Main.rb require './BookShelf'
require './Book'
bookShelf = BookShelf.new(4)
bookShelf.appendBook(Book.new("AAAAA"))
bookShelf.appendBook(Book.new("BBBBB"))
bookShelf.appendBook(Book.new("CCCCC"))
bookShelf.appendBook(Book.new("DDDDD"))
i = 0;
while (i < bookShelf.getCount() do
book = bookShelf.getBookAt(i)
i += 1
puts book.getName()
end
|
Iteratorパターンを使用した例 BookShelf.rb require './BookShelfIterator'
class BookShelf
def initialize(maxsize)
@books = Array.new(maxsize)
@last = 0
end
def getBookAt(index)
return @books[index]
end
def appendBook(book)
@books[@last] = book
@last += 1
end
def getCount()
return @last
end
def iterator()
return BookShelfIterator.new(self)
end
end
IIterator.rb class IIterator
def initialize()
end
def hasNext()
puts "hasNext メソッドを定義してください。";
end
def next()
puts "next メソッドを定義してください。";
end
end
BookShelfIterator.rb require './IIterator'
class BookShelfIterator < IIterator
def initialize(bookShelf)
super();
@bookShelf = bookShelf
@index = 0
end
def hasNext()
return @index < @bookShelf.getCount()
end
def next()
book = @bookShelf.getBookAt(@index)
@index += 1
return book
end
end
Main.rb require './BookShelf'
require './Book'
bookShelf = BookShelf.new(4)
bookShelf.appendBook(Book.new("AAAAA"))
bookShelf.appendBook(Book.new("BBBBB"))
bookShelf.appendBook(Book.new("CCCCC"))
bookShelf.appendBook(Book.new("DDDDD"))
it = bookShelf.iterator()
while it.hasNext() do
book = it.next()
puts book.getName()
end
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.py class BookShelf:
def __init__(self, maxsize)
self.__books = list(range(maxsize)
self.__last = 0
def getBookAt(self, index):
return self.__books[index]
def appendBook(self, book):
self.__books[self.__last] = book
self.__last += 1
def getCount(self):
return self.__last
Main.py from Book import Book
from BookShelf import BookShelf
bookShelf = BookShelf.new(4)
bookShelf.appendBook(Book.new("AAAAA"))
bookShelf.appendBook(Book.new("BBBBB"))
bookShelf.appendBook(Book.new("CCCCC"))
bookShelf.appendBook(Book.new("DDDDD"))
for i in range(bookShelf.getCount()):
book = bookShelf.getBookAt(i)
print(book.getName())
|
Iteratorパターンを使用した例 BookShelf.py from BookShelfIterator import BookShelfIterator
class BookShelf:
def __init__(self, maxsize)
self.__books = list(range(maxsize)
self.__last = 0
def getBookAt(self, index):
return self.__books[index]
def appendBook(self, book):
self.__books[self.__last] = book
self.__last += 1
def getCount(self):
return self.__last
def iterator(self):
return BookShelfIterator(self)
IIterator.py from abc import ABCMeta, abstractmethod
class IIterator(metaclass=ABCMeta): # インタフェース
def hasNext(self):
pass
def next(self):
pass
BookShelfIterator.py from Book import Book
from IIterator import IIterator
class BookShelfIterator(IIterator):
def __init__(self, bookShelf):
self.__bookShelf = bookShelf
self.__index = 0
def hasNext(self):
return self.__index < self__bookShelf.getCount()
def next(self):
book = self__bookShelf.getBookAt(self.__index)
self.__index += 1
return book
Main.py from Book import Book
from BookShelf import BookShelf
bookShelf = BookShelf.new(4)
bookShelf.appendBook(Book.new("AAAAA"))
bookShelf.appendBook(Book.new("BBBBB"))
bookShelf.appendBook(Book.new("CCCCC"))
bookShelf.appendBook(Book.new("DDDDD"))
it = bookShelf.iterator()
while it.hasNext()):
book = it.next()
print(book.getName())
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.php <?php
class BookShelf {
public function __construct() {
$this->books = array();
}
public function getBookAt($index) {
return $this->books[$index];
}
public function appendBook($book) {
$this->books[] = $book;
}
public function getCount() {
return count($this->books);
}
}
?>
Main.py <?php
require_once('BookShelf.php');
require_once('Book.php');
$bookShelf = new BookShelf()
$bookShelf->appendBook(new Book("AAAAA"))
$bookShelf->appendBook(new Book("BBBBB"))
$bookShelf->appendBook(new Book("CCCCC"))
$bookShelf->appendBook(new Book("DDDDD"))
$i = 0;
while($i < $bookShelf->getCount()) {
$book = $bookShelf->getBookAt($i++);
print $book->getName() . "\n";
}
?>
|
Iteratorパターンを使用した例 BookShelf.php <?php
require_once('BookShelfIterator.php');
class BookShelf {
public function __construct() {
$this->books = array();
}
public function getBookAt($index) {
return $this->books[$index];
}
public function appendBook($book) {
$this->books[] = $book;
}
public function getCount() {
return count($this->books);
}
public function iterator() {
return new BookShelfIterator($this);
}
}
?>
IIterator.php <?php
interface IIterator {
public function hasNext();
public function next();
}
?>
BookShelfIterator.php <?php
require_once('IIterator.php');
class BookShelfIterator implements IIterator {
public function __construct($bookShelf) {
$this->bookShelf = $bookShelf;
$this->index = 0;
}
public function hasNext() {
return $this->index < $this->bookShelf->getCount();
}
public function next() {
++$this->index;
return $this->bookShelf->getBookAt($this->index - 1);
}
}
?>
Main.php <?php
require_once('BookShelf.php');
require_once('Book.php');
$bookShelf = new BookShelf();
$bookShelf->appendBook(Book.new("AAAAA"));
$bookShelf->appendBook(Book.new("BBBBB"));
$bookShelf->appendBook(Book.new("CCCCC"));
$bookShelf->appendBook(Book.new("DDDDD"));
$it = $bookShelf->iterator();
while($it->hasNext()) {
$book = $it->next();
print $book->getName() . "\n";
}
?>
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 なお、PHP には、Iterator インタフェースもありますが、メソッドが next() や current() なのでここでは使用しませんでした。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.ts import {Book} from "./Book";
export
class BookShelf {
private books:Array<Book>;
private last:number;
public constructor(maxsize:number) {
this.books = new Array<Book>(maxsize);
}
public getBookAt(index:number):Book {
return this.books[index];
}
public appendBook(book:Book):void {
this.books[this.last++] = book;
}
public getCount():number {
return this.last;
}
}
Main.ts import {BookShelf} from "./BookShelf";
import {Book} from "./Book";
let bookShelf:BookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
let i:number = 0;
while (i < bookShelf.getCount()) {
let book:Book = bookShelf.getBookAt(i++);
process.stdout.write(book.getName() + "\n");
}
|
Iteratorパターンを使用した例 BookShelf.ts import {Book} from "./Book";
import {IIterator} from "./IIterator";
import {BookShelfIterator} from "./BookShelfIterator";
export
class BookShelf {
private books:Array<Book>;
private last:number = 0;
public constructor(maxsize:number) {
this.books = new Array<Book>(maxsize);
}
public getBookAt(index:number):Book {
return this.books[index];
}
public appendBook(book:Book):void {
this.books[this.last++] = book;
}
public getCount():number {
return this.last;
}
public iterator():IIterator<Book> {
return new BookShelfIterator(this);
}
}
IIterator.ts export
interface IIterator<T> {
hasNext():boolean;
next():T;
}
BookShelfIterator.ts import {BookShelf} from "./BookShelf";
import {IIterator} from "./IIterator";
import {Book} from "./Book";
export
class BookShelfIterator implements IIterator<Book> {
private bookShelf:BookShelf;
private index:number = 0;
public constructor(bookShelf:BookShelf) {
this.bookShelf = bookShelf;
}
public hasNext():boolean {
return (this.index < this.bookShelf.getCount());
}
public next():Book {
return this.bookShelf.getBookAt(index++);
}
}
Main.ts import {BookShelf} from "./BookShelf";
import {Book} from "./Book";
import {IIterator} from "./IIterator";
let bookShelf:BookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
let it:IIterator<Book> = bookShelf.iterator();
while (it.hasNext()) {
let book:Book = it.next();
process.stdout.write(book.getName() + "\n");
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.swift public class BookShelf {
private var books:[Book]
private var last:Int = 0
public init(_ maxsize:Int) {
books = Array<Book>(repeating:Book(""), count:maxsize)
}
public func getBookAt(_ index:Int) -> Book {
return books[index]
}
public func appendBook(_ book:Book) {
books[last] = book
last += 1
}
public getCount() -> Int {
return last
}
}
Main.swift let bookShelf:BookShelf = BookShelf(4)
bookShelf.appendBook(Book("AAAAA"))
bookShelf.appendBook(Book("BBBBB"))
bookShelf.appendBook(Book("CCCCC"))
bookShelf.appendBook(Book("DDDDD"))
for i in 0..< bookShelf.getCount()) {
let book:Book = bookShelf.getBookAt(i)
print(book.getName())
}
|
Iteratorパターンを使用した例 BookShelf.swift public class BookShelf {
private var books:[Book]
private var last:Int = 0
public init(_ maxsize:Int) {
this.books = Array<Book>(repeating:Book(""), count:maxsize)
}
public func getBookAt(_ index:Int) -> Book {
return books[index]
}
public func appendBook(_ book:Book) {
books[last] = book
last += 1
}
public func getCount() -> Int {
return last
}
public iterator() -> IIterator {
return BookShelfIterator(self)
}
}
IIterator.swift public protocol IIterator {
func hasNext() -> Bool
func next() -> Book
}
BookShelfIterator.swift public class BookShelfIterator : IIterator<Book> {
private var bookShelf:BookShelf
private var index:Int = 0
public init(bookShelf:BookShelf) {
self.bookShelf = bookShelf
}
public func hasNext() -> Bool {
return index < bookShelf.getCount()
}
public func next() -> Book {
index += 1
return bookShelf.getBookAt(index - 1)
}
}
Main.swift let bookShelf:BookShelf = BookShelf(4)
bookShelf.appendBook(Book("AAAAA"))
bookShelf.appendBook(Book("BBBBB"))
bookShelf.appendBook(Book("CCCCC"))
bookShelf.appendBook(Book("DDDDD"))
var it:IIterator = bookShelf.iterator()
while (it.hasNext()) {
let book:Book = it.next()
print(book.getName())
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.kt class BookShelf(maxsize: Int) {
private val books:ArrayList<Book> = ArrayList(maxsize)
private var last: Int = 0
fun getBookAt(index: Int): Book {
return books[index]
}
fun appendBook(book: Book) {
books.add(book)
last++
}
fun getCount(): Int {
return last
}
}
Main.kt fun main() {
val bookShelf = BookShelf(4)
bookShelf.appendBook(Book("AAAAA"))
bookShelf.appendBook(Book("BBBBB"))
bookShelf.appendBook(Book("CCCCC"))
bookShelf.appendBook(Book("DDDDD"))
var i: Int = 0
while (i < bookShelf.getCount()) {
val book: Book = bookShelf.getBookAt(i++)
println(book.name)
}
}
|
Iteratorパターンを使用した例 BookShelf.kt class BookShelf(maxsize: Int) {
private val books: ArrayList<Book> = ArrayList(maxsize)
private var last: int = 0
fun getBookAt(index: Int): Book {
return books[index]
}
fun appendBook(book: Book) {
books.add(book)
last++
}
fun getCount(): Int {
return last
}
operator fun iterator(): IIterator<Book> {
return BookShelfIterator(this)
}
}
IIterator.kt interface IIterator<T> {
operator fun hasNext(): Boolean
operator fun next(): T
}
BookShelfIterator.kt class BookShelfIterator(val bookShelf: BookShelf) : IIterator<Book> {
private var index: Int = 0
override operator fun hasNext(): Boolean {
return index < bookShelf.getCount()
}
override operator fun next(): Book {
return bookShelf.getBookAt(index++)
}
}
Main.kt fun main() {
val bookShelf:BookShelf = BookShelf(4)
bookShelf.appendBook(Book("AAAAA"))
bookShelf.appendBook(Book("BBBBB"))
bookShelf.appendBook(Book("CCCCC"))
bookShelf.appendBook(Book("DDDDD"))
val it = bookShelf.iterator()
while (it.hasNext()) {
val book = it.next()
println(book.name)
}
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.scala class BookShelf(maxsize: Int) {
private val books = new Array[Book](maxsize)
private var last: Int = 0
def getBookAt(index: Int): Book = books(index)
def appendBook(book: Book) {
books(last) = book
last += 1
}
def getCount(): Int = last
}
Main.scala object Main {
def main(args: Array[String]) {
val bookShelf = new BookShelf(4)
bookShelf.appendBook(new Book("AAAAA"))
bookShelf.appendBook(new Book("BBBBB"))
bookShelf.appendBook(new Book("CCCCC"))
bookShelf.appendBook(new Book("DDDDD"))
var i: Int = 0
while (i < bookShelf.getCount()) {
val book: Book = bookShelf.getBookAt(i)
i += 1
System.out.println(book.name)
}
}
}
|
Iteratorパターンを使用した例 BookShelf.scala class BookShelf(maxsize: Int) {
private val books = new Array[Book](maxsize)
private var last: int = 0
def getBookAt(index: Int): Book = books(index)
def appendBook(book: Book) {
books(last) = book
last += 1
}
def getCount(): Int = last
def iterator(): IIterator[Book] = new BookShelfIterator(this)
}
IIterator.scala trait IIterator[T] {
def hasNext() : Boolean
def next() : T
}
BookShelfIterator.scala class BookShelfIterator(val bookShelf: BookShelf) extends IIterator[Book] {
private var index: Int = 0
def hasNext() : Boolean = index < bookShelf.getCount()
def next() : Book = bookShelf.getBookAt({index += 1; index - 1})
}
Main.scala object Main {
def main(args: Array[String]) {
val bookShelf = new BookShelf(4)
bookShelf.appendBook(new Book("AAAAA"))
bookShelf.appendBook(new Book("BBBBB"))
bookShelf.appendBook(new Book("CCCCC"))
bookShelf.appendBook(new Book("DDDDD"))
val it:IIterator[Book] = bookShelf.iterator()
while (it.hasNext()) {
val book: Book = it.next()
System.out.println(book.name)
}
}
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.groovy class BookShelf {
private Book[] books
private int last = 0
BookShelf(int maxsize) {
this.books = new Book[maxsize]
}
Book getBookAt(int index) {
return books[index]
}
void appendBook(Book book) {
this.books[last++] = book
}
int getCount() {
return last
}
}
Main.groovy public class Main {
static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4)
bookShelf.appendBook(new Book("AAAAA"))
bookShelf.appendBook(new Book("BBBBB"))
bookShelf.appendBook(new Book("CCCCC"))
bookShelf.appendBook(new Book("DDDDD"))
int i = 0
while (i < bookShelf.getCount()) {
Book book = bookShelf.getBookAt(i++)
System.out.println(book.name)
}
}
}
|
Iteratorパターンを使用した例 BookShelf.groovy class BookShelf {
private Book[] books
private int last = 0
BookShelf(int maxsize) {
this.books = new Book[maxsize]
}
Book getBookAt(int index) {
return books[index]
}
void appendBook(Book book) {
this.books[last++] = book
}
int getCount() {
return last
}
IIterator<Book> iterator() {
return new BookShelfIterator(this)
}
}
IIterator.groovy interface IIterator<T> {
abstract boolean hasNext()
abstract T next()
}
BookShelfIterator.groovy public class BookShelfIterator implements IIterator<Book> {
private BookShelf bookShelf
private int index
BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf
this.index = 0
}
boolean hasNext() {
return (index < bookShelf.getCount())
}
Book next() {
return bookShelf.getBookAt(index++)
}
}
Main.groovy public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4)
bookShelf.appendBook(new Book("AAAAA"))
bookShelf.appendBook(new Book("BBBBB"))
bookShelf.appendBook(new Book("CCCCC"))
bookShelf.appendBook(new Book("DDDDD"))
IIterator<Book> it = bookShelf.iterator()
while (it.hasNext()) {
Book book = it.next()
System.out.println(book.name)
}
}
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.go type BookShelf struct {
books []*Book
}
func (self *BookShelf) GetBookAt(index int) *Book {
return self.books[index]
}
func (self *BookShelf) AppendBook(book *Book) {
self.books = append(self.books, book)
}
func (self *BookShelf) GetCount() int {
return len(self.books)
}
func NewBookShelf() *BookShelf {
return &BookShelf {}
}
Main.go type main {
var bookShelf = NewBookShelf()
bookShelf.AppendBook(NewBook("AAAAA"))
bookShelf.AppendBook(NewBook("BBBBB"))
bookShelf.AppendBook(NewBook("CCCCC"))
bookShelf.AppendBook(NewBook("DDDDD"))
var i = 0
for i < bookShelf.GetCount() {
fmt.Println(bookShelf.GetBookAt(i).Name)
i++
}
}
|
Iteratorパターンを使用した例 BookShelf.go type BookShelf struct {
books []*Book
}
func (self *BookShelf) GetBookAt(index int) *Book {
return self.books[index]
}
func (self *BookShelf) AppendBook(book *Book) {
self.books = append(self.books, book)
}
func (self *BookShelf) GetCount() int {
return len(self.books)
}
func (self *BookShelf) Iterator() *BookShelfIterator {
return NewBookShelfIterator(self)
}
func NewBookShelf() *BookShelf {
return &BookShelf {}
}
IIterator.go type IIterator interface {
HasNext() bool
Next() *Book
}
BookShelfIterator.go type BookShelfIterator struct {
IIterator
bookShelf *BookShelf
index int
}
func (self *BookShelfIterator) HasNext() bool {
return self.index < self.BookShelf.GetCount()
}
func (self *BookShelfIterator) Next() *Book {
var book = self.BookShelf.GetBookAt(self.index)
self.index++
return book
}
func NewBookShelfIterator(bookShelf *BookShelf) *BookShelfIterator {
return &BookShelfIterator{
BookShelf: bookShelf,
index: 0,
}
}
Main.go type main {
var bookShelf = NewBookShelf()
bookShelf.AppendBook(NewBook("AAAAA"))
bookShelf.AppendBook(NewBook("BBBBB"))
bookShelf.AppendBook(NewBook("CCCCC"))
bookShelf.AppendBook(NewBook("DDDDD"))
var it = bookShelf.iterator()
for it.HasNext() {
var book = it.Next()
fmt.Println(book.Name)
}
}
|
|
main の繰り返しの部分で BookShelf の GetBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは GetBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは HasNext()、データの取り出しは Next() です。 BookShelf クラスに Iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの Iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのHasNext()を呼ぶことによって、BookShelf インスタンスの GetCount() を呼び出しデータの終わりかどうかを判定し、また、Next()を呼ぶことによって、GetBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 bookShelf.d import book;
public class BookShelf {
private Book[] books;
private int last = 0;
public this(in int maxsize) {
this.books = new Book[maxsize];
}
public Book getBookAt(in int index) {
return books[index];
}
public void appendBook(Book book) {
this.books[last++] = book;
}
public int getCount() {
return last;
}
}
main.d import std.stdio;
import book;
import bookshelf;
int main() {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
int i = 0;
while (i < bookShelf.getCount()) {
Book book = bookShelf.getBookAt(i++);
writeln(book.getName());
}
return 0;
}
|
Iteratorパターンを使用した例 bookshelf.d import book;
import iiterator;
import bookshelfiterator;
public class BookShelf {
private Book[] books;
private int last = 0;
public this(in int maxsize) {
this.books = new Book[maxsize];
}
public Book getBookAt(in int index) {
return books[index];
}
public void appendBook(Book book) {
this.books[last++] = book;
}
public int getCount() {
return last;
}
public IIterator!(Book) iterator() {
return new BookShelfIterator(this);
}
}
iiterator.d public interface IIterator(T) {
public abstract boolean hasNext();
public abstract T next();
}
bookshelfiterator.d import book;
import iiterator;
import bookshelf;
public class BookShelfIterator : IIterator!(Book) {
private BookShelf bookShelf;
private int index;
public this(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
public boolean hasNext() {
return (index < bookShelf.getCount());
}
public Book next() {
return bookShelf.getBookAt(index++);
}
}
main.d import std.stdio;
import book;
import iiterator;
import bookshelf;
public int main() {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("AAAAA"));
bookShelf.appendBook(new Book("BBBBB"));
bookShelf.appendBook(new Book("CCCCC"));
bookShelf.appendBook(new Book("DDDDD"));
IIterator!(Book) it = bookShelf.iterator();
while (it.hasNext()) {
Book book = it.next();
writeln(book.getName());
}
return 0;
}
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています(java.util.Iterator もありますが、ここではあえて使用せず、IIterator を自作しています)。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |
既存クラス
|
Iteratorパターンを使用しない例 BookShelf.pas unit UnitBookShelf;
interface
uses
UnitBook;
type
BookShelf = class
private
var books:array of Book;
var last:integer;
public
constructor Create(maxsize:integer);
destructor Destroy(); override;
function getBookAt(index:integer):Book;
procedure appendBook(book:Book);
function getCount():integer;
end;
implementation
constructor BookShelf.Create(maxsize:integer);
begin
inherited Create();
last := 0;
SetLength(books, maxsize);
end;
destructor BookShelf.Destroy();
var _book:Book;
begin
for _book in books do
_book.Free;
Finalize(books);
end;
function BookShelf.getBookAt(index:integer):Book;
begin
Result := books[index];
end;
procedure BookShelf.appendBook(book:Book);
begin
books[last] := book;
INC(last);
end;
function BookShelf.getCount():integer;
begin
Result := last;
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitBook,
UnitBookShelf;
var _bookShelf:BookShelf;
var _book:Book;
var i:integer;
begin
_bookShelf := BookShelf.Create(4);
_bookShelf.appendBook(Book.Create('AAAAA'));
_bookShelf.appendBook(Book.Create('BBBBB'));
_bookShelf.appendBook(Book.Create('CCCCC'));
_bookShelf.appendBook(Book.Create('DDDDD'));
i := 0;
while (i < bookShelf.getCount()) do begin
_book := bookShelf.getBookAt(i);
INC(i);
writeln(_book.getName());
end;
end.
|
Iteratorパターンを使用した例 BookShelf.pas unit UnitBookShelf;
interface
uses
UnitBook,
UnitIIterator;
type
BookShelf = class
private
var
books:array of Book;
last:integer;
public
constructor Create(maxsize:integer);
destructor Destroy(); override;
function getBookAt(index:integer):Book;
procedure appendBook(book:Book);
function getCount():integer;
function iterator():IIterator<Book>;
end;
implementation
uses
UnitBookShelfIterator; // 循環参照を防ぐため
constructor BookShelf.Create(maxsize:integer);
begin
inherited Create();
SetLength(books, maxsize);
end;
destructor BookShelf.Destroy();
var _book:Book;
begin
for _book in books do
_book.Free;
Finalize(books);
end;
function BookShelf.getBookAt(index:integer):Book;
begin
Result := books[index];
end;
procedure BookShelf.appendBook(book:Book);
begin
books[last] := book;
INC(last);
end;
function BookShelf.getCount():integer;
begin
Result := last;
end;
function BookShelf.iterator():IIterator<Book>;
begin
Result := BookShelfIterator.Create(self);
end;
end.
IIterator.pas unit UnitIIterator;
interface
type
IIterator<T> = interface
function hasNext:Boolean;
function next:T;
end;
implementation
end.
BookShelfIterator.pas unit UnitBookShelfIterator;
interface
uses
UnitBook,
UnitBookShelf,
UnitIIterator;
type
BookShelfIterator = class(TInterfacedObject, IIterator<Book>)
var
_bookShelf:BookShelf;
index:integer;
public
constructor Create(_bookShelf:BookShelf);
function hasNext():Boolean;
function next():Book;
end;
implementation
constructor BookShelfIterator.Create(_bookShelf:BookShelf);
begin
self._bookShelf := _bookShelf;
index := 0;
end;
function BookShelfIterator.hasNext():Boolean;
begin
Result := index < _bookShelf.getCount();
end;
function BookShelfIterator.next():Book;
begin
Result := _bookShelf.getBookAt(index);
INC(index);
end;
Main.dpr program Main;
uses
System.SysUtils,
UnitBook,
UnitBookShelf,
UnitIIterator,
UnitBookShelfIterator;
var
_bookShelf:BookShelf;
_book:Book;
it:IIterator<Book>;
begin
_bookShelf := BookShelf.Create(4);
_bookShelf.appendBook(Book.Create('AAAAA'));
_bookShelf.appendBook(Book.Create('BBBBB'));
_bookShelf.appendBook(Book.Create('CCCCC'));
_bookShelf.appendBook(Book.Create('DDDDD'));
it := _bookShelf.iterator();
while (it.hasNext()) do
begin
_book := it.next();
writeln(_book.getName());
end;
end.
|
|
main の繰り返しの部分で BookShelf の getBookAt() というメソッドを呼んでいます。つまり、main で BookShelf に依存したコーディングがされているということです。もしBookShelf でない別のクラスからデータを取り出すことになったら、メソッドは getBookAt() ではないかもしれません。仕様変更のたびに、ソースを見直さなければなりません。 |
データがまだあるかどうかは hasNext()、データの取り出しは next() です。 BookShelf クラスに iterator() メソッド、そして、IIterator を継承(インタフェースなので、インプリメント)した BookShelfIterator クラスが追加されています。 main からBookShelf インスタンスの iterator() メソッドを呼ぶことによって、BookShelf インスタンスを持った BookShelfIterator インスタンスが生成されます。それが main の it にセットされます。 そして、BookShelfIterator インスタンスのhasNext()を呼ぶことによって、BookShelf インスタンスの getCount() を呼び出しデータの終わりかどうかを判定し、また、next()を呼ぶことによって、getBookAt() を呼び出しデータを取り出しています。 |