具有逻辑的 Guice AssistedInjection Factory
Guice AssistedInjection Factory with logic
我一直在为一个项目使用 guice。
我有一个抽象 class,它有很多实现。为了使用正确的实现,我使用了一个接收参数的工厂,然后 returns 正确的实例。
演示代码
@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
的实现(注意他们应该使用辅助注入)?
谢谢。
You will still need MyFactory to choose an implementation based on your id
, though 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
方法 return 是你的子类 B。如果你想 return 你的超类 A 的方法,隐藏具体类型,你可以这样做;那么您将需要 implement
调用,因为 Guice 不知道要尝试调用哪个构造函数。
如果您想强制消费者对实现进行编码,您可能需要引用仅 return 接口的工厂。 隐藏实现细节 通常是个好主意,并且可能涉及使用方法 A create(Bar bar)
创建 A.Factory
并将其与 implement
连接起来.但是,这里是不必要的,因为您的 MyFactory 已经 returns A 并隐藏了实现子类(在逻辑上表现得像 A.Factory
),并且因为您需要 @Named
或其他一些限定符注释来区分您正在创建的两个 A.Factory
绑定。简而言之,这是额外的并发症,对这种特定情况没有任何好处。
我一直在为一个项目使用 guice。
我有一个抽象 class,它有很多实现。为了使用正确的实现,我使用了一个接收参数的工厂,然后 returns 正确的实例。
演示代码
@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
的实现(注意他们应该使用辅助注入)?
谢谢。
You will still need MyFactory to choose an implementation based on your id
, though 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
方法 return 是你的子类 B。如果你想 return 你的超类 A 的方法,隐藏具体类型,你可以这样做;那么您将需要 implement
调用,因为 Guice 不知道要尝试调用哪个构造函数。
如果您想强制消费者对实现进行编码,您可能需要引用仅 return 接口的工厂。 隐藏实现细节 通常是个好主意,并且可能涉及使用方法 A create(Bar bar)
创建 A.Factory
并将其与 implement
连接起来.但是,这里是不必要的,因为您的 MyFactory 已经 returns A 并隐藏了实现子类(在逻辑上表现得像 A.Factory
),并且因为您需要 @Named
或其他一些限定符注释来区分您正在创建的两个 A.Factory
绑定。简而言之,这是额外的并发症,对这种特定情况没有任何好处。