我是 Guice 的新手,我想知道我能走多远。
我有一个接口(interface)UserInfo
具有多个实现类 GoogleUserInfo
, FacebookUserInfo
, TwitterUserInfo
等等。这些类是使用工厂创建的
public class UserInfoFactory {
public UserInfo createFromJsonString(String jsonspec) {
.
.
.
}
}
创建由 JSON 字符串
jsonspec
控制控制 UserInfo
的哪些实现类被退回。具体来说,有一个 JSON 字符串元素 domain
它控制着创作。创建确实是 jsonspec
的反序列化函数使用 GSON。我想知道是否有一种用 Guice 依赖注入(inject)替换这个创建的好方法?
最佳答案
您可以将 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
,您将无法注入(inject)任何 TwitterUserInfo
的依赖关系,或它的依赖关系的依赖关系——这就是 Guice 很好地解决的问题类型。可以注入(inject)
TwitterUserInfo
作为 Provider
,这将使您能够访问尽可能多的完全注入(inject)的 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 { /* ... */ }
}
}
...当然,这也允许您注入(inject)
@Twitter Provider<UserInfo>
如果您只需要接口(interface)并且希望将来某个时候更改具体类。如果你想要TwitterUserInfo
接受构造函数参数,Assisted injection将帮助您创建 TwitterUserInfoFactory
不过,这将有助于它走向 immutability :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
)可能是最好的方法。虽然解耦接口(interface)和类以简化测试是件好事,但维护和理解是有成本的。 Guice 是一把非常强大的锤子,但并非所有东西实际上都是要敲的钉子。
关于guice - 用 Guice 代替抽象工厂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16002484/