4

私は Guice を初めて使用し、どこまでできるのか疑問に思っていました。、などのUserInfo複数の実装クラスとのインターフェースがあります。これらのクラスは、ファクトリを使用して作成されますGoogleUserInfoFacebookUserInfoTwitterUserInfo

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

  }
}

作成は、返さjsonspecれる実装クラスを制御するJSON 文字列によって制御されます。UserInfo具体的にはdomain、作成を制御する JSON 文字列要素があります。作成は、実際にはjsonspecGSON を使用した逆シリアル化の機能です。
この作成を Guice 依存性注入に置き換える良い方法があるかどうか疑問に思っていましたか?

4

3 に答える 3

7

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

として注入できます。これにより、完全に注入されたオブジェクトに好きなだけアクセスできます。TwitterUserInfoProviderTwitterUserInfo

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 は非常に強力なハンマーですが、すべてが実際にハンマーで打たれるわけではありません。

于 2013-04-15T23:32:21.803 に答える
1

おそらく、補助注射を使用したいと思うでしょう。

GoogleUserInfo、FacebookUserInfo、および TwitterUserInfo のコンストラクターに (@Assisted String jsonspec) (そしてもちろん @Inject) で注釈を付ける必要があります。

次に、ファクトリ クラスを構成する必要があります。

binder.install(new FactoryModuleBuilder().build(UserInfoFactory.class));

次に、使用する Info プロバイダーを適切にバインドします。

思います。私は自分自身をガイドするのはかなり新しいです。

于 2013-04-14T18:12:51.070 に答える