Guice AssistedInjection Factory具有逻辑功能

时间:2018-06-08 19:15:43

标签: java guice

我一直在为项目使用guice。

我有一个抽象类,它有很多实现。要使用正确的实现,我使用一个接收参数的工厂,然后返回正确的实例。

演示代码

@Singleton
public class MyFactory {

    private final Foo foo;

    @Inject
    public MyFactory(final Foo foo) {
        this.foo = foo;
    }

    public A create(final Bar bar) {
        switch (bar) {
            case 0:
                return new B(foo, bar);
            case 1:
                return new C(foo, bar);
            //this goes on
        }
    }
}

public abstract A {
    public A(final Bar bar) {
        //do sth
    }
}

public B extends A {
    private final Foo foo;

    public B(final Foo foo, final Bar bar) {
        super(bar);
        this.foo = foo;
    }
}

public C extends A {
    private final Foo foo;

    public C(final Foo foo, final Bar bar) {
        super(bar);
        this.foo = foo;
    }
}

我想知道的是,如果我可以用Guice替换工厂直接注入A的实现(注意它们应该使用辅助注入)?

感谢。

1 个答案:

答案 0 :(得分:1)

You will still need MyFactory根据您的id选择实施,your assisted injection can be very short

// No need for this to be @Singleton;
// if you want the same shared Foo instance, make it @Singleton
public class MyFactory {

    private final B.Factory bFactory;
    private final C.Factory cFactory;

    @Inject
    public MyFactory(B.Factory bFactory, C.Factory cFactory) {
        this.bFactory = bFactory;
        this.cFactory = cFactory;
    }

    public A create(final Bar bar) {
        switch (bar.getSomeInteger()) {   // I assume you're checking a
                                          // property of bar
            case 0:
                return bFactory.create(bar);
            case 1:
                return cFactory.create(bar);
            //this goes on
        }
    }
}

public B extends A {
    public interface Factory {
        B create(Bar bar);
    }

    private final Foo foo;

    public B(final Foo foo, @Assisted final Bar bar) {
        super(bar);
        this.foo = foo;
    }
}

public C extends A {
    public interface Factory {
        C create(Bar bar);
    }

    private final Foo foo;

    public C(final Foo foo, @Assisted final Bar bar) {
        super(bar);
        this.foo = foo;
    }
}

你的模块:

public class YourModule extends AbstractModule {
  @Override public void configure() {
    install(new FactoryModuleBuilder().build(B.Factory.class));
    install(new FactoryModuleBuilder().build(C.Factory.class));
  }
}

编辑:在我的示例中,需要在FactoryModuleBuilder上调用implement,因为B.Factory有一个create返回你的子类B的方法。如果你想让方法返回你的超类A,隐藏具体类型,你可以这样做;然后你需要implement调用,因为Guice不知道要尝试调用哪个构造函数。

如果您想强制使用者对实现进行编码,您可能需要引用仅返回该接口的工厂。这通常是隐藏实现细节的好主意,并且可能涉及使用方法A.Factory创建A create(Bar bar)并将其与implement连接起来。但是,在这里是不必要的,因为你的MyFactory已经返回A并隐藏了实现子类(用A.Factory表示逻辑),因为你需要@Named或其他一些限定符注释,以区分您正在创建的两个A.Factory绑定。简而言之,这种额外的并发症对这种特殊情况没有任何好处。