PerlでPrototypeパターン! (デザインパターン)
Perlでデザインパターン 第6弾(Prototypeパターン)
Prototypeパターンとは、クラスからインスタンスを生成するのではなく、インスタンスから別のインスタンスを作り出すデザインパターンです。
一般的なPrototypeパターンのクラス図
関連 +---------------------+ +---------------------+ | Client |------------>| prototype | +---------------------+ +---------------------+ | | | | +---------------------+ +---------------------+ | | | createClone | +---------------------+ +---------------------+ # | 継承 | +----------+----------+ | Concreteprottype | +---------------------+ | | +---------------------+ | createClone | | | +---------------------+
サンプル
一番下で紹介している本の『Java言語で学ぶデザインパターン入門』に書かれているPrototypeパターンのJavaでのサンプルをPerlで書き換えてみました。
サンプルのクラス図
+---------------------+ +---------------------+ | Manager |------------>| Product | +---------------------+ +---------------------+ | showcase | | | +---------------------+ +---------------------+ | register | | clone | | create | | createClone | | | | use | +---------------------+ +---------------------+ # | +------------------+-------------------+ | | +----------+----------+ +----------+----------+ | MessageBox | | UnderlinePen | +---------------------+ +---------------------+ | ulchar | | decochar | +---------------------+ +---------------------+ | createClone | | createClone | | use | | use | | | | | +---------------------+ +---------------------+
Product.pm
package Product; use strict; use warnings; sub clone { my $dmy = shift; my $self = shift; my $class = shift; return bless $self, $class; } sub createClone { die "オーバーライド必須"; } sub use { die "オーバーライド必須"; }
Manager.pm
package Manager; use strict; use warnings; sub new { my $class = shift; my $self = {}; $self->{showcase} = {}; return bless $self, $class; } sub register { my $self = shift; my ($name, $proto) = @_; $self->{showcase}->{$name} = $proto; } sub create { my $self = shift; my $protoname = shift; my $p = $self->{showcase}->{$protoname}; return $p->createClone; } 1;
静的にソースを見ていると、どこにも宣言していないcreateCloneがエラーにならないのかと思いますが、$pには、動的にProductクラスのオブジェクトが渡されるので、大丈夫のようです。
MessageBox.pm
package MessageBox; use strict; use warnings; use base 'Product'; sub new { my $class = shift; my $self = {}; $self->{decochar} = shift; return bless $self, $class; } sub use { my $self = shift; my $s = shift; for (my $i = 0; $i < length($s) + 4; $i++) { print $self->{decochar}; } print "\n"; print "$self->{decochar} $s $self->{decochar}\n"; for (my $i = 0; $i < length($s) + 4; $i++) { print $self->{decochar}; } print "\n"; } sub createClone { my $self = shift; my $class = ref($self); return Product->clone({%{$self}}, $class); } 1;
ref($self)でクラス名を取得し、%{$self}でオブジェクトをデリファレンスしてクラス変数を取得しています。
UnderlinePen.pm
package UnderlinePen; use strict; use warnings; use base 'Product'; sub new { my $class = shift; my $self = {}; $self->{ulchar} = shift; return bless $self, $class; } sub use { my $self = shift; my $s = shift; print "\"$s\"\n"; for (my $i = 0; $i < length($s) + 2; $i++) { print $self->{ulchar}; } print "\n"; } sub createClone { my $self = shift; my $class = ref($self); return Product->clone({%{$self}}, $class); } 1;
Main.pl
use strict; use warnings; use Manager; use UnderlinePen; use MessageBox; # 準備 my $manager = Manager->new; my $upen = UnderlinePen->new('~'); my $mbox = MessageBox->new('*'); my $sbox = MessageBox->new('/'); $manager->register("strong message", $upen); $manager->register("warning box", $mbox); $manager->register("slash box", $sbox); # 生成 my $p1 = $manager->create("strong message"); $p1->use("Hello, world."); my $p2 = $manager->create("warning box"); $p2->use("Hello, world."); my $p3 = $manager->create("slash box"); $p3->use("Hello, world.");
実行結果
C:\Documents and Settings\dp\prototype>perl main.pl "Hello, world." ~~~~~~~~~~~~~~~ ***************** * Hello, world. * ***************** ///////////////// / Hello, world. / /////////////////
尚、本コンテンツは、結城先生の以下の本をかなり参考にしています。
Javaでデザインパターンを勉強したい人には、お勧めのご著書です!
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/06/19
- メディア: 大型本
- 購入: 51人 クリック: 762回
- この商品を含むブログ (400件) を見る