Guice をファクトリに統合することもできますが、コードはこの場合とまったく同じようにしたほうがよいでしょう。
これは、実際には簡単に置き換えることができないファクトリの 1 つです。これは、 を解析し、jsonSpec
それに基づいて返される具象型を変更するロジックを含める必要があるためです。もう少し単純化されていないバージョンのファクトリが次のようになっているとします。
public class UserInfoFactory {
public UserInfo createFromJsonString(String jsonspec) {
if(getUserType(jsonSpec) == TWITTER) {
return new TwitterUserInfo(jsonSpec);
} else { /* ... */ }
}
private UserInfoType getUserType(String jsonSpec) { /* ... */ }
}
その論理はどこかに住んでいなければならず、あなた自身UserInfoFactory
は完璧な家のように思えます. ただし、 を使用しているため、の依存関係またはその依存関係の依存関係を注入することnew
はできません。これは、Guice がうまく解決するタイプの問題です。TwitterUserInfo
として注入できます。これにより、完全に注入されたオブジェクトに好きなだけアクセスできます。TwitterUserInfo
Provider
TwitterUserInfo
public class UserInfoFactory {
@Inject Provider<TwitterUserInfo> twitterUserInfoProvider;
public UserInfo createFromJsonString(String jsonspec) {
if(getUserType(jsonSpec) == TWITTER) {
TwitterUserInfo tui = twitterUserInfoProvider.get();
tui.initFromJson(jsonSpec);
return tui;
} else { /* ... */ }
}
}
...そしてもちろん、@Twitter Provider<UserInfo>
インターフェイスだけが必要で、将来いつか具象クラスを変更したい場合は、 a を注入することもできます。TwitterUserInfo
コンストラクターのパラメーターを受け入れたい場合は、アシスト インジェクション をTwitterUserInfoFactory
使用すると、不変性を高めるのに役立ちますが、作成するのに役立ちます。
public class UserInfoFactory {
@Inject TwitterUserInfo.Factory twitterUserInfoFactory;
public UserInfo createFromJsonString(String jsonspec) {
if(getUserType(jsonSpec) == TWITTER) {
return twitterUserInfoFactory.create(jsonSpec);
} else { /* ... */ }
}
}
// binder.install(new FactoryModuleBuilder().build(TwitterUserInfoFactory.class));
public class TwitterUserInfo implements UserInfo {
public interface Factory {
TwitterUserInfo create(String jsonSpec);
}
public TwitterUserInfo(@Assisted String jsonSpec, OtherDependency dep) { /* ... */ }
}
最後の注意: TwitterUserInfo
には依存関係がない可能性が高いです。私にはデータ オブジェクトのように聞こえます。そのため、( を使用してnew
) クラスを正確に見つけたままにしておくことが、おそらく最善の方法です。テストを容易にするためにインターフェースとクラスを切り離すのは良いことですが、メンテナンスと理解にはコストがかかります。Guice は非常に強力なハンマーですが、すべてが実際にハンマーで打たれるわけではありません。