您可以将 Guice 集成到工厂中,但在这种情况下,您的代码可能会更好。
这实际上是那些不能轻易替换的工厂之一,因为它必须包含逻辑来解析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
,您将无法注入任何TwitterUserInfo
' 依赖项,或其依赖项' 的依赖项——这是 Guice 很好地解决的问题类型。
您可以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 是一把非常强大的锤子,但并非所有东西实际上都是要敲的钉子。