せっかくの休日なのになんにもやる気がおこらずだらだらする。。。なにがきっかけかもう忘れたけど、そんなだらだらな日は↓の本をPerlでだらだら書いてみることにする。
23パターンのうち半分くらいはちゃんと理解しているつもり。人にちゃんと説明できる、書ける、使える、そんな立派な大人にならないといけない。
Iteratorインターフェースから。
package Iterator;
use strict;
use warnings;
sub has_next { die; }
sub get_next { die; }
1;
Aggregaterインターフェース。
package Aggregate;
use strict;
use warnings;
sub iterator { die; }
1;
今回扱うオブジェクトのBookクラス。
package Book;
use strict;
use warnings;
sub new {
my ($class, $name) = @_;
my $self = {
name => $name,
};
return bless $self, $class;
}
sub name {
return shift->{name};
}
1;
Bookオブジェクトの集まり、Bookshelf。Aggregateを実装する。
package Bookshelf;
use strict;
use warnings;
use base qw/Aggregate/;
use BookshelfIterator;
sub new {
my ($class, $maxsize) = @_;
my $self = {
maxsize => $maxsize || 5,
books => [],
};
return bless $self, $class;
}
### implements Aggregate::iterator
sub iterator {
my $self = shift;
return BookshelfIterator->new($self);
}
sub get_book_at {
my ($self, $index) = @_;
return $self->{books}->[$index];
}
sub append_book {
my ($self, $book) = @_;
if (scalar @{$self->{books}} < $self->{maxsize}) {
push @{$self->{books}}, $book;
}
}
sub get_length {
return scalar @{shift->{books}};
}
1;
maxsizeの扱いは不親切。警告なし、追加しない。
この集まりBookshelfをスキャンしてIteratorとして扱えるようにする、BookshelfIterator。Iteratorを実装する。
package BookshelfIterator;
use strict;
use warnings;
use base qw/Iterator/;
use Bookshelf;
sub new {
my ($class, $bookshelf) = @_;
my $self = {
bookshelf => $bookshelf,
id => 0,
};
return bless $self, $class;
}
### implements Iterator::has_next
sub has_next {
my $self = shift;
return $self->{id} < $self->{bookshelf}->get_length() ? 1 : 0;
}
### implements Iterator::get_next
sub get_next {
my $self = shift;
my $book = $self->{bookshelf}->get_book_at($self->{id});
$self->{id}++;
return $book;
}
1;
使ってみる。
#!/usr/bin/perl
use strict;
use warnings;
use Book;
use Bookshelf;
my $bookshelf = Bookshelf->new(4);
$bookshelf->append_book(Book->new("デザインパターン入門"));
$bookshelf->append_book(Book->new("Perl Best Practices"));
$bookshelf->append_book(Book->new("ウェブ進化論"));
$bookshelf->append_book(Book->new("その日のまえに"));
my $it = $bookshelf->iterator();
while ($it->has_next()) {
my $book = $it->get_next();
print $book->name() , "\n";
}
ようするに、
Iteratorパターンとは、何かがたくさん集まっているときに、それを順番に指し示していき、全体をスキャンしていく処理を行うためのものです。
ということ。もっとPerlらしい実装はあるだろうけど。
すこし、だらだらな1日を抜け出した気がする。。。