2006年3月19日

せっかくの休日なのになんにもやる気がおこらずだらだらする。。。なにがきっかけかもう忘れたけど、そんなだらだらな日は↓の本をPerlでだらだら書いてみることにする。

増補改訂版Java言語で学ぶデザインパターン入門
増補改訂版Java言語で学ぶデザインパターン入門結城 浩

ソフトバンククリエイティブ 2004-06-19
売り上げランキング : 7,578

おすすめ平均 star
star僭越ながら助言です
starデザインパターンのバイブル的存在
starデザインパターンの解説書としては平凡

Amazonで詳しく見る
by G-Tools

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日を抜け出した気がする。。。

Comments

トラックバック

トラックバックURL: