.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Object::Container::ja 3pm" .TH Object::Container::ja 3pm "2010-10-12" "perl v5.18.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Object::Container::ja \- シンプルなオブジェクトコンテナインタフェース .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Object::Container; \& \& ## OO インタフェース \& # 初期化 \& my $container = Object::Container\->new; \& \& # クラスを登録 \& $container\->register(\*(AqHTML::TreeBuilder\*(Aq); \& \& # クラスをイニシャライザ指定して登録 \& $container\->register(\*(AqWWW::Mechanize\*(Aq, sub { \& my $mech = WWW::Mechanize\->new( stack_depth => 1 ); \& $mech\->agent_alias(\*(AqWindows IE 6\*(Aq); \& return $mech; \& }); \& \& # 登録したオブジェクトを得る \& my $mech = $container\->get(\*(AqWWW::Mechanize\*(Aq); \& \& ## Singletonインタフェース \& my $container = Object::Container\->instance; \& \& # Singletonインタフェースの場合はregister/getはクラスメソッドとして動作する \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq); \& my $mech = Object::Container\->get(\*(AqWWW::Mechanize\*(Aq); \& \& # Singletonインタフェースはget関数を任意の名前でエクスポートできる \& use Object::Container \*(Aqcontainer\*(Aq; \& container\->register(\*(AqWWW::Mechanize\*(Aq); \& my $mech = container\->get(\*(AqWWW::Mechanize\*(Aq); \& my $mech = container(\*(AqWWW::Mechanize\*(Aq); # save as above \& \& # Singletonインタフェースのサブクラス化 \& package MyObj; \& use Object::Container \*(Aq\-base\*(Aq; \& \& register \*(Aqua\*(Aq => sub { LWP::UserAgent\->new }; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Object::Container は Singleton インタフェース、OO インタフェースどちらでもつかえるシンプルなオブジェクトコンテナーを提供するモジュールです。 .PP アプリケーション中で同一のオブジェクトをいろいろな場所で使用したい場合があるかもしれません。 そのような場合に、Class::Singleton などを使用してどこからでもそのオブジェクトを取り出せるように設計することがありますが、この方法だと使用したいクラスをサブクラス化して使用する必要があります。 .PP このモジュールではオブジェクトを複数格納できるコンテナーを提供し、コンテナー自身を Singleton にすることで複数のオブジェクトを簡単にどこからでもアクセスできるようにすることができます。 .PP 設計思想は Object::Registrar というモジュールに似ていますが、OOインターフェースを持つ点、登録されたオブジェクトの初期化を実際に必要になるまで行わない (遅延実行)点が異なっています。 .SS "OOインターフェースとSingletonインターフェース" .IX Subsection "OOインターフェースとSingletonインターフェース" このモジュールは \s-1OO\s0 インターフェースと Singleton インタフェースの二種類のインターフェースを持ちます。 .PP OOインターフェスは .PP .Vb 1 \& my $container = Object::Container\->new; .Ve .PP などのようにコンストラクタを呼び、その返り値のオブジェクトを介してオブジェクトの登録や取得を行います。この場合登録したオブジェクトはコンテナーオブジェクトごとに独立しています。 .PP 例えば .PP .Vb 2 \& my $container1 = Object::Container\->new; \& my $container2 = Object::Container\->new; .Ve .PP などのように複数のコンテナーを使い分けるような使い方ができます。 .PP Singletonインタフェースは .PP .Vb 1 \& my $container = Object::Container\->instance; .Ve .PP というように明示的にコンストラクタをよばす、クラスに割り当てられた唯一のオブジェクトを使用するインターフェースです。 .PP Singletonインタフェースを使用する場合は、register や get 関数などは .PP .Vb 1 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq, sub { WWW::Mechanize\->new( stack_depth => 1 ) }); .Ve .PP というようにすべてクラスメソッドとして使用することができます。Singletonインターフェースで複数のコンテナーを使いたい場合はサブクラス化をして .PP .Vb 2 \& MyContainer1\->get(\*(AqWWW::Mechanize\*(Aq); \& MyContainer2\->get(\*(AqWWW::Mechanize\*(Aq); .Ve .PP のようにします。 .SS "SingletonインタフェースとEXPORT関数" .IX Subsection "SingletonインタフェースとEXPORT関数" Singletonインタフェースで、いちいち .PP .Vb 1 \& MyContainer\->get(\*(AqWWW::Mechanize\*(Aq); .Ve .PP と書くのがだるい、と言う人のために好きな名前でコンテナをEXPORTできる機能を用意してあります。 .PP .Vb 1 \& use MyContainer \*(Aqobj\*(Aq; .Ve .PP と、use 時にエクスポートしたい関数名を指定します。すると .PP .Vb 1 \& obj\->register( mech => sub { WWW::Mechanize\->new }); \& \& obj\->get(\*(Aqmech\*(Aq); \& obj(\*(Aqmech\*(Aq); # shortcut to obj\->get(\*(Aqmech\*(Aq) .Ve .PP などと短い書き方でコンテナーにアクセスできるようになります。 .SS "Singletonインタフェースとサブクラス化" .IX Subsection "Singletonインタフェースとサブクラス化" Singletonインタフェースのサブクラス内でオブジェクトを登録したいときに .PP .Vb 1 \& _\|_PACKAGE_\|_\->register( mech => sub { WWW::Mechanize\->new } ); .Ve .PP と書くのがだるい、と言う人のためにサブクラス化時のインタフェースも用意してあります。 .PP サブクラス化するときに、 .PP .Vb 1 \& use base \*(AqObject::Container\*(Aq; .Ve .PP とするかわりに .PP .Vb 1 \& use Object::Container \*(Aq\-base\*(Aq; .Ve .PP とすると register と言う関数がエクスポートされます。こうすると上記の \f(CW\*(C`_\|_PACKAGE_\|_\->register\*(C'\fR のかわりに .PP .Vb 1 \& register mech => sub { WWW::Mechanize\->new }; .Ve .PP と書くことができるようになります。 .SS "遅延ロードと依存性解決" .IX Subsection "遅延ロードと依存性解決" registerメソッドで登録されたオブジェクトは、初回の get メソッドを実行したときに初めて初期化されます。 .PP .Vb 2 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq, sub { WWW::Mechanize\->new }); # ここで WWW::Mechanize\->new は実行されない \& my $mech = Object::Container\->get(\*(AqWWW::Mechanize\*(Aq); # ここで実行される .Ve .PP この機能により大量にクラスが登録されていても、必要な物のみ初期化されるためリソースを大量に消費することがないため永続プロセス以外でも手軽に導入できるでしょう。 .PP また Singleton インタフェースは初期化関数と組み合わせることにより、オブジェクト同士の依存性の解決も行うことができます。 .PP たとえば、HTTP::Cookies オブジェクトに依存した LWP::UserAgent を考えます。このような場合、 .PP .Vb 5 \& Object::Container\->register(\*(AqHTTP::Cookies\*(Aq, sub { HTTP::Cookies\->new( file => \*(Aq/path/to/cookie.dat\*(Aq ) }); \& Object::Container\->register(\*(AqLWP::UserAgent\*(Aq, sub { \& my $cookies = Object::Container\->get(\*(AqHTTP::Cookies\*(Aq); \& LWP::UserAgent\->new( cookie_jar => $cookies ); \& }); .Ve .PP というように初期化関数のなかで get メソッドをしようすることで依存性の解決が行えます。 .PP 上記の場合、 .PP .Vb 1 \& my $ua = Object::Container\->get(\*(AqLWP::UserAgent\*(Aq); .Ve .PP した場合に LWP::UserAgent と HTTP::Cookies の両方が初期化されます。 .PP もし、登録と同時に初期化したい場合、以下のようにできます。 .PP .Vb 1 \& Object::Container\->register({ class => \*(AqLWP::UserAgent\*(Aq, preload => 1 }); .Ve .PP \&\fIinitializer\fR オプションを指定することができます。 .PP .Vb 5 \& Object::Container\->register({ class => \*(AqWWW::Mechanize\*(Aq, initializer => sub { \& my $mech = WWW::Mechanize\->new( stack_depth ); \& $mech\->agent_alias(\*(AqWindows IE 6\*(Aq); \& return $mech; \& }, preload => 1 }); .Ve .PP これは、以下のように書くのと同じです。 .PP .Vb 6 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq, sub { \& my $mech = WWW::Mechanize\->new( stack_depth ); \& $mech\->agent_alias(\*(AqWindows IE 6\*(Aq); \& return $mech; \& }); \& Object::Container\->get(\*(AqWWW::Mechanize\*(Aq); .Ve .PP \&\fIargs\fR オプションを指定した場合は: .PP .Vb 1 \& Object::Container\->register({ class => \*(AqLWP::UserAgent\*(Aq, args => \e@args, preload => 1 }); .Ve .PP これは、もうおわかりのように、以下と同じです。 .PP .Vb 2 \& Object::Container\->register(\*(AqLWP::UserAgent\*(Aq, @args); \& Object::Container\->get(\*(AqLWP::UserAgent\*(Aq); .Ve .SH "METHODS" .IX Header "METHODS" .ie n .SS "register( $class, @args )" .el .SS "register( \f(CW$class\fP, \f(CW@args\fP )" .IX Subsection "register( $class, @args )" .ie n .SS "register( $class_or_name, $initialize_code )" .el .SS "register( \f(CW$class_or_name\fP, \f(CW$initialize_code\fP )" .IX Subsection "register( $class_or_name, $initialize_code )" Object::Container にオブジェクトを登録します。 .PP いちばんシンプルな使い方は .PP .Vb 1 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq); .Ve .PP などのようにクラス名のみを登録する方法です。この場合 get した場合に WWW::Mechanize\->new が引数なしで呼ばれます。 .PP new の引数を指定したい場合は .PP .Vb 1 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq, @constructor_args); .Ve .PP などのように第二引数以降に配列をわたせばそれがそのまま new にわたされます。 .PP new 以外のコンストラクタが必要な場合、他に初期化処理が必要な場合、依存しているモジュールがある場合などは、第二引数にコードリファレンスを渡すことで任意の初期化処理が行えます。 .PP .Vb 5 \& Object::Container\->register(\*(AqWWW::Mechanize\*(Aq, sub { \& my $mech = WWW::Mechanize\->new( stack_depth ); \& $mech\->agent_alias(\*(AqWindows IE 6\*(Aq); \& return $mech; \& }); .Ve .PP このコードリファレンスではコンテナに格納するオブジェクトを返す必要があります。 .PP またこのように初期化関数を渡す場合、第一引数ではクラス名を与える必要はなく任意の名前を与えることができます。 .PP .Vb 2 \& Object::Container\->register(\*(Aqua1\*(Aq, sub { LWP::UserAgent\->new }); \& Object::Container\->register(\*(Aqua2\*(Aq, sub { LWP::UserAgent\->new }); .Ve .PP などと言った使い方も可能です。 .SS "get($class_or_name)" .IX Subsection "get($class_or_name)" registerメソッドで登録したオブジェクトを取得します。 .PP 与える引数はregisterメソッドに与えた第一引数と同じ物を渡します。 .SS "ensure_class_loaded($class)" .IX Subsection "ensure_class_loaded($class)" \&\f(CW$class\fR がロードされているか確認し、ロードされていなかった場合そのクラスを use してくれるユーティリティ関数です。 .PP 初期化関数に依存性を含ませるような場合でその依存モジュールを遅延ロードしたい場合などに使用すると便利です。 .SS "load_all" .IX Subsection "load_all" .SS "load_all_except(@classes_or_names)" .IX Subsection "load_all_except(@classes_or_names)" 基本的にこのモジュールは必要になるまで(getメソッドが呼ばれるまで)オブジェクトを初期化しませんが、 \&\f(CW\*(C`Copy\-On\-Write\*(C'\fR や、実行時の速度を重視する場合など、あらかじめオブジェクトを初期化しておきたい場合があるかもしれません。そのような場合には .PP .Vb 1 \& Object::Container\->load_all; .Ve .PP とすることで全てのオブジェクトを初期化済みにすることができます。 .PP また、特定のオブジェクトだけは初期化したくないという場合、 .PP .Vb 1 \& Object::Container\->load_all_except(qw/Foo Bar/); .Ve .PP などとすると初期化したくないオブジェクト以外の全てのオブジェクトを初期化することも出来ます。 上記の場合は Foo と Bar と言うオブジェクト以外の全てのオブジェクトを初期化します。 .SH "EXPORT FUNCTIONS ON SUBCLASS INTERFACE" .IX Header "EXPORT FUNCTIONS ON SUBCLASS INTERFACE" .Vb 4 \& package MyContainer; \& use strict; \& use warnings; \& use Object::Container \*(Aq\-base\*(Aq; .Ve .PP とすることで Object::Container を継承し独自のコンテナークラスを定義することが出来ます。 .PP このサブクラス中では以下の関数をしようしてオブジェクト定義をすることができます。 .ie n .SS "register( $class, @args )" .el .SS "register( \f(CW$class\fP, \f(CW@args\fP )" .IX Subsection "register( $class, @args )" .ie n .SS "register( $class_or_name, $initialize_code )" .el .SS "register( \f(CW$class_or_name\fP, \f(CW$initialize_code\fP )" .IX Subsection "register( $class_or_name, $initialize_code )" .Vb 5 \& register Foo => sub { \& my ($self) = @_; \& $self\->ensure_class_loaded(\*(AqFoo\*(Aq); \& Foo\->new; \& }; .Ve .PP オブジェクトを登録します。上述したクラス(オブジェクト)メソッドの \f(CW\*(C`register\*(C'\fR メソッドとおなじ役割をします。 .SS "preload(@classes_or_names)" .IX Subsection "preload(@classes_or_names)" .SS "preload_all" .IX Subsection "preload_all" .SS "preload_all_except" .IX Subsection "preload_all_except" これらはクラス(オブジェクト)メソッドの \f(CW\*(C`load_all\*(C'\fR、\f(CW\*(C`load_all_except\*(C'\fR と同じようにつかえる関数で、その名前の通り \f(CW\*(C`preload_all\*(C'\fR が \f(CW\*(C`load_all\*(C'\fR と、\f(CW\*(C`preload_all_except\*(C'\fR が \f(CW\*(C`load_all_except\*(C'\fR とそれぞれ対応しています。 .SH "SEE ALSO" .IX Header "SEE ALSO" Class::Singleton, Object::Registrar. .SH "AUTHOR" .IX Header "AUTHOR" Daisuke Murase .SH "COPYRIGHT & LICENSE" .IX Header "COPYRIGHT & LICENSE" Copyright (c) 2009 by \s-1KAYAC\s0 Inc. .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP The full text of the license can be found in the \&\s-1LICENSE\s0 file included with this module.