用Guice取代抽象工厂? [英] Replacing abstract factory with Guice?

查看:62
本文介绍了用Guice取代抽象工厂?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Guice的新手,我想知道我能走多远. 我有一个具有多个实现类GoogleUserInfoFacebookUserInfoTwitterUserInfo等的接口UserInfo.这些类是使用工厂创建的

I am new to Guice and I was wondering how far I can take it. I have an interface UserInfo with multiple implementing classes GoogleUserInfo, FacebookUserInfo, TwitterUserInfo etc. These classes are created using a factory

public class UserInfoFactory {
  public UserInfo createFromJsonString(String jsonspec) {
    .
    .
    .

  }
}

创建由JSON字符串jsonspec控制,该字符串控制返回UserInfo的哪些实现类.具体来说,有一个JSON字符串元素domain来控制创建.创建实际上是使用GSON对jsonspec进行反序列化的功能.
我想知道是否有一种好的方法可以用Guice依赖项注入来替换此创建?

The creation is controlled by the JSON string jsonspec which controls which of the implementing classes of UserInfo is returned. Specifically, there is a JSON string element domain which controls the creation. The creation really is a function of the deserialization of jsonspec using GSON.
I was wondering if there is a good way to replace this creation with a Guice dependency injection?

推荐答案

您可以将Guice集成到工厂中,但是您的代码可能比这种情况下更好.

You can integrate Guice into the factory, but your code is probably better off exactly as it is in this case.

这实际上是不容易替换的工厂之一,因为它必须包含解析jsonSpec并根据其更改返回的具体类型的逻辑.假设工厂的简化版本看起来像这样:

This is actually one of those Factories that can't be replaced easily, because it has to contain the logic to parse out the jsonSpec and change which concrete type it returns based on that. Let's say the slightly-less-simplified version of the factory looks like this:

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很好解决的问题类型

That logic has to live somewhere, and your own UserInfoFactory seems like a perfect home. However, because you use new, you would not be able to inject any of TwitterUserInfo's dependencies, or its dependencies' dependencies--and that is the type of problem that Guice solves nicely.

可以TwitterUserInfo作为Provider注入,这将使您可以根据需要访问尽可能多的完全注入的TwitterUserInfo对象:

You can inject TwitterUserInfo as a Provider, which will give you access to as many of fully-injected TwitterUserInfo objects as you'd like:

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>.如果您希望TwitterUserInfo接受构造函数参数,请辅助注入 将会帮助您创建TwitterUserInfoFactory,它将帮助它创建不变性:

...and, of course, that also allows you to inject a @Twitter Provider<UserInfo> if you only need the interface and want to vary the concrete class sometime in the future. If you want TwitterUserInfo to accept constructor parameters, Assisted injection will help you create a TwitterUserInfoFactory though, which will help it toward 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 )可能是最好的方法.分离接口和类以简化测试是很不错的,但是维护和理解会付出一定的代价. Guice是一把非常有力的锤子,但并非所有东西实际上都是要锤击的钉子.

A final note: TwitterUserInfo likely doesn't have any dependencies--it sounds like a data object to me--so leaving your class exactly how you found it (with new) is probably the best approach. While it's nice to have decoupled interfaces and classes to ease testing, there is a cost in maintenance and understanding. Guice is a very powerful hammer, but not everything is actually a nail to be hammered.

这篇关于用Guice取代抽象工厂?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆