我一直在为项目使用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
的实现(注意它们应该使用辅助注入)?
感谢。
答案 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
绑定。简而言之,这种额外的并发症对这种特殊情况没有任何好处。