生成されたファクトリー
Nette DIは、インターフェイスを元にファクトリーコードを自動生成することができるので、コードを書く手間が省けます。
ファクトリーは、オブジェクトを作成し、設定するクラスです。したがって、その依存関係も同様に渡します。ファクトリーメソッド*デザインパターンと混同しないように注意してください。
そんな工場の姿を序章で紹介しました:
Nette
DIはファクトリーコードを自動生成することができます。インターフェイスを作成するだけで、Nette
DIが実装を生成してくれます。インターフェースは、create
という名前のメソッドを1つだけ持ち、戻り値の型を宣言する必要があります。
つまり、ファクトリーArticleFactory
は、オブジェクトを作成するメソッドcreate
を持っていますArticle
。クラスArticle
は、たとえば次のようなものになるでしょう。
設定ファイルにファクトリーを追加します。
Nette DIは、対応するファクトリーの実装を生成します。
このように、ファクトリーを利用するコードでは、インターフェースでオブジェクトを要求し、生成された実装をネットDIが利用します。
パラメタライズドファクトリー
ファクトリーメソッドcreate
はパラメータを受け取ることができ、それをコンストラクタに渡します。例えば、記事の著者IDをクラスArticle
に追加してみましょう。
また、ファクトリーにパラメータを追加します。
コンストラクタのパラメータとファクトリーのパラメータは同じ名前なので、ネットDIは自動的にこれらを渡します。
高度な定義
定義は、キーimplement
を使って複数行で記述することも可能です。
この長い書き方では,通常のサービスと同様に,コンストラクタの引数をarguments
で,設定をsetup
で追加することが可能です.
例:メソッドcreate()
がパラメータ$authorId
を受け付けない場合,コンストラクタArticle
に渡される固定値を設定に指定することができる.
あるいは逆に、create()
がパラメータ$authorId
を受け付けたが、それがコンストラクタの一部ではなく、メソッドArticle::setAuthorId()
から渡された場合、セクションsetup
でそれを参照することになる。
アクセッサー
Netteではファクトリーの他に、いわゆるアクセサーを生成することができます。アクセサーとは、DIコンテナから特定のサービスを返すget()
メソッドを持つオブジェクトです。get()
を複数回呼び出すと、常に同じインスタンスが返されます。
アクセッサは、依存関係にレイジーローディングをもたらします。例えば、エラーを特殊なデータベースに記録するクラスがあるとします。もしデータベース接続をコンストラクタの依存関係として渡した場合、
接続は常に作成する必要がありますが、エラーが発生したときにしか使われないので、
接続はほとんど使われないままです。
その代わりに、このクラスはアクセサを渡すことができ、そのget()
メソッドが呼ばれたときだけ、データベースオブジェクトが作成されます。
アクセサを作るには?インターフェイスを書くだけで、ネットDIが実装を生成してくれます。インターフェイスは、get
というメソッドを1つだけ持ち、戻り値の型を宣言しなければなりません。
アクセッサが返すサービスの定義と一緒に、設定ファイルにアクセッサを追加してください。
このアクセサはPDO
というタイプのサービスを返します。
このようなサービスは設定に1つしかないので、アクセサはそれを返します。このタイプのサービスが複数設定されている場合、どのサービスを返すかをその名前を使って指定できます。たとえば、- PDOAccessor(@db1)
。
マルチファクトリー/アクセサー
今までのファクトリーとアクセッサは、1つのオブジェクトを作成するか返すだけでした。アクセッサと組み合わせたマルチファクトリーも作成することができます。このようなマルチファクトリークラスのインターフェイスは
create<name>()
と
get<name>()
と呼ばれる複数のメソッドで構成されます。
生成された複数のファクトリーとアクセッサを渡す代わりに、複雑なマルチファクトリーを1つだけ渡すことができます。
あるいは、複数のメソッドの代わりに、get()
をパラメータ付きで使うこともできる:
この場合、MultiFactory::getArticle()
はMultiFactoryAlt::get('article')
と同じことをする。 しかし、この代替構文にはいくつかの欠点がある。どの$name
値がサポートされているのかが明確でないことと、複数の異なる$name
値を使用する場合、インターフェイスで戻り値の型を指定できないことである。
リストを使った定義
この方法は、コンフィギュレーションで複数のファクトリーを定義するのに使える:.{data-version:3.2.0}
あるいは、ファクトリーの定義で、参照を使用して既存のサービスを参照できます:
タグ付き定義
マルチファクトリーを定義するもう一つの方法は、タグを使うことです。