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