Guice、FactoryModuleBuilder、多个实现和泛型



我使用的是Guice和FactoryModueBuilder。通常,只定义工厂的接口就足够了,Guice会自动注入实现。

然而,我感到困难的是,工厂中的方法使用泛型。假设我有以下内容。由接口定义的构造实例的基本类型。

interface Foo<T> {
    T get();
}

以及下面两个类定义的Foo接口的两个实现。

class FooA<T> implements Foo<T> {
    @Inject
    FooA(@Assisted Class<T> clazz, @Assisted String s) {...}
}
class FooB<T> implements Foo<T> {
    @Inject
    FooB(@Assisted Class<T> clazz, @Assisted Integer i) {...}
}

然后我有了下面定义的工厂接口,使用了两个自定义绑定注释,允许我使用多个实现。

interface FooFactory {
    @A Foo<T> build(Class<T> clazz, String s);
    @B Foo<T> build(Class<T> clazz, Integer i);
}

我已经尝试了许多可能的解决方案,到目前为止,除了一个之外,其他都奏效了。成功的解决方案基本上是编写我自己的FooFactory实现,如下所示。并在模块的configure方法中,将接口绑定到实现中;bind(FooFactory.class).to(FooFactoryImpl.class);

class FooFactoryImpl {
    Foo<T> build(Class<T> clazz, String s) {
        return new FooA(clazz, s):
    }
    Foo<T> build(Class<T> clazz, Integer i) {
        return new FooB(clazz, i);
    }
}

然而,我对这个解决方案有一个问题。这些实例不是由Guice创建的,因此我丢失了Guice附带的null检查。这与我的其他没有这个问题的工厂截然不同。这意味着我必须为Foo的每个实现显式地编写空检查。我想避免这种情况。

以下是我尝试过的一些解决方案。

解决方案1:

FactoryModuleBuilder fmb = new FactoryModuleBuilder()
    .implement(Foo.class, A.class, FooA.class)
    .implement(Foo.class, B.class, FooB.class);
install(fmb.build(FooFactory.class));

解决方案2:

FactoryModuleBuilder fmb = new FactoryModuleBuilder()
    .implement(TypeLiteral.get(Foo.class), A.class, TypeLiteral.get(FooA.class))
    .implement(TypeLiteral.get(Foo.class), B.class, TypeLiteral.get(FooB.class));
install(fmb.build(TypeLiteral.get(FooFactory.class)));

GitHub上提供了示例代码(如果有人感兴趣的话)。

据我所知,你不能设计AssistedInject工厂以这种方式工作。然而,在我看来,你在一节课上做得太多了。因为您对Class<T>没有任何限制,所以很明显,您在构造函数中没有使用此类的任何方法,这意味着,将行为重构到一个单独的类中应该相当容易。我知道这有点像样板,这不是你想要的,但它可能看起来像这样:

interface FooDataFactory {
    @A FooData build(String s);
    @B FooData build(Integer i);
}
public class FooA<T> implements Foo<T> {
    public FooA(FooData data) {
        // You should know what class you need when you're actually calling the constructor.
        // This way you don't even need to pass around Class<T> instances
    }
}

如果这种方法不适用于您的用例,请告诉我,我将进行编辑以进行补偿。

相关内容

  • 没有找到相关文章

最新更新