DIって本当に必要? その4
http://d.hatena.ne.jp/higayasuo/20070417#1176813784の続き。
前回のエントリーでDIContainerが提供する機能で重要なのは
- AOP
- スコープ管理
で、IoCがDIContainerの敷居を高くしていると書きました。それでは、どうしたらよいのでしょうか。
必要なオブジェクトは、自分から取りにいけばよいのです。たとえば、AOPとスコープ管理を低要するFactoryクラスがあるとします。
使うときには、次のように呼び出します。
public class Factory {
public staticT getInstance(Class<? extends T> type) {
...
}
}
このFactoryクラスを使ったときのClientクラスは次のようになります。
Service service = Factory.getInstance(Serivice.class);
Serviceクラスを使いたいと思ったら、自分からFactory.getInstance()を呼び出せばよいのです。DIの設定のためのファイルやコードも不要です。テストのときには、setService()メソッドを通じてモックを設定してあげればこれまでのDIと同様に簡単にテストすることができます。
class Client {
Service service = Factory.getInstance(Serivice.class);
void setService(Service service) {
this.service = service;
}
void go() {
service.go();
}
}
Factory.getInstance()に依存したらPOJOじゃないじゃん。という声が聞こえてきそうです。それでは、Guice版のコードと比べてみましょう。
@Inject Service service;
- Factory
の二つがどれほど違うというのでしょうか。テストのしやすさという点ではどちらも一緒です。「いきすぎたPOJO信仰」がFactoryに依存するのをためらわすのです。効果は一緒なのに。
Service service = Factory.getInstance(Serivice.class);
Factoryを直接呼び出すメリットは、DIの設定が不要であることだけでなく、直接newされるようなオブジェクトでもFactoryを通じて必要なオブジェクトが取得できるということです。
また、各フレームワークがDIContainerにいちいち対応する必要もありません。これは、どういう意味かというと、たとえば、StrutsのActionでDIContainerで管理されているオブジェクトを使いたい場合、これまでだと、StrutsをDIContainerに対応させるために、Actionが生成されるタイミングでDIContainerと連携を取るグルーコードを書く必要がありました。
しかし、Factoryを使う場合は、グルーコードは不要です。必要なときに自ら呼び出せばよいのですから。
テストのしやすさという面では、実はこれまでのDIよりもやりやすくなっています。これまでのDIでは設定ファイルなしでテストする場合、必要なプロパティをすべて手動で設定する必要があり、面倒でした。
Factoryを使う場合は、プロパティが全部設定された上で、必要なものだけモックで上書きすることができます。