guice - 用 Guice 代替抽象工厂?

标签 guice factory-pattern

我是 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/

相关文章:

php - 我应该如何在 Laravel 中正确构建我的单元测试

c# - 使用访问者模式从平面 DTO 构建对象图

java - Guice:何时开始在 headless JAR 中进行注入(inject)/引导?

java - Guice:如何进行后期绑定(bind)?

java - 如何在应用程序中访问 Play Framework 2.4 guice Injector?

python - 是否可以将 Flask 中的 "app factory"模式用于 Click CLI 应用程序?

java - 如何在运行时基于没有 XML 的 Spring 属性注入(inject)不同的服务

java - 在 AWS Lambda 中集成 Google Guice

java - Shiro 路径模式排除

delphi - 从 TObject 转换为接口(interface)类型