AbstractFactory
最後の方は疲れてきてIteratorを使うべき所を横着している。きちんとクラス図を書いて整理するとなるほどと思う。Compositeパターンも絡んでくるとやや面倒。is-aとhas-aをきちんと区別できるかどうか。フォルダとファイルの構造と同じ。フォルダの中にフォルダはある。folder has a folder だけれども、ファイルはフォルダを保持できない。
use strict; use warnings; { package Factory::Item; use strict; use warnings; sub new { my ($class, $caption) = @_; my $self = { caption => $caption, }; return bless $self, $class; } sub makeHTML { die; } } { package Factory::Link; use strict; use warnings; our @ISA = qw/Factory::Item/; sub new { my ($class, $caption, $url) = @_; my $self = { caption => $caption, url => $url, }; return bless $self, $class; } } { package Factory::Tray; use strict; use warnings; our @ISA = qw/Factory::Item/; sub new { my ($class, $caption) = @_; my $self = { caption => $caption, tray => [], }; return bless $self, $class; } sub add { my ($self, $item) = @_; push @{$self->{tray}}, $item; } } { package Factory::Page; use strict; use warnings; sub new { my ($class, $title, $author) = @_; my $self = { title => $title, author => $author, content => [], }; return bless $self, $class; } sub add { my ($self, $item) = @_; push @{$self->{content}}, $item; } sub output { my $self = shift; $self->makeHTML(); } sub makeHTML { die; } } { package Factory::Factory; use strict; use warnings; sub getFactory { my ($class, $string) = @_; return $string->new(); } sub createLink { die; } sub createTray { die; } sub createPage { die; } } { package ListFactory; use strict; use warnings; our @ISA = qw/Factory::Factory/; sub new { my ($class, ) = @_; return bless {}, $class; } sub createLink { my ($class, $caption, $url) = @_; return ListFactory::ListLink->new($caption, $url); } sub createTray { my ($class, $caption) = @_; return ListFactory::ListTray->new($caption); } sub createPage { my ($class, $title, $author) = @_; return ListFactory::ListPage->new($title, $author); } } { package ListFactory::ListTray; use strict; use warnings; use Data::Dumper; our @ISA = qw/Factory::Tray/; sub new { my ($class, $caption) = @_; return $class->SUPER::new($caption); } sub makeHTML { my $self = shift; my $buffer = ''; $buffer .= "<li>\n".$self->{caption}."\n"; $buffer .= "<ul>\n"; $buffer .= $self->{tray}[0]->makeHTML(); $buffer .= $self->{tray}[1]->makeHTML()."</ul>\n"; $buffer .= "</li>\n"; return $buffer; } } { package ListFactory::ListLink; use strict; use warnings; use Data::Dumper; our @ISA = qw/Factory::Link/; sub new { my ($class, $caption, $url) = @_; return $class->SUPER::new($caption, $url); } sub makeHTML { my $self = shift; return "<li><a href='".$self->{url}."' >".$self->{caption}."</a></li>\n"; } } { package ListFactory::ListPage; use strict; use warnings; use Data::Dumper; our @ISA = qw/Factory::Page/; sub new { my ($class, $title, $author) = @_; return $class->SUPER::new($title, $author); } sub makeHTML { my $self = shift; my $buffer = ''; $buffer .= "<html><head><title>".$self->{title}."</title></head>\n"; $buffer .= "<body>\n"; $buffer .= "<h1>".$self->{title}."</h1>\n"; $buffer .= "<ul>\n"; $buffer .= $self->{content}[0]->makeHTML(); $buffer .= "</ul>\n"; print $buffer; } } my $factory = Factory::Factory->getFactory('ListFactory'); my $asahi = $factory->createLink('asahi_shinbun', "http://localhost"); my $yomiuri = $factory->createLink('yomiuri_shinbun', "http://localhost"); my $tray_news = $factory->createTray("newsPaper"); $tray_news->add($asahi); $tray_news->add($yomiuri); my $page = $factory->createPage('TEST_PAGE', 'taro'); $page->add($tray_news); $page->output();