以下是我编写的工厂模式。但是,为了将其更改为提供程序,Guice documentation并没有帮助。
class ClientA extends AbstractClient {...}
class ClientB extends AbstractClient {...}
class ClientUtil {
private static AbstractClient client;
public static AbstractClient getClient(String key) {
ClientType clientType = ....
switch(clientType) {
case ".." : client = new ClientA.Builder()....build();
break;
case "..." :
default : client= new ClientB.Builder()....build();
}
return client;
}
}
class Application {
AbstractClient client = ClientUtil.getClient(key); // here, key is a string which is dynamic
}
请提供一些有关如何使用Guice AssistedInject以提供者格式编写的建议。
答案 0 :(得分:1)
您是否尝试过手动编写Factory?您链接的手册中有一个很好的例子,您的代码可以轻松转换为Guice。
public interface ClientFactory {
AbstractClient create(String key);
}
public class ClientFactoryImpl implements ClientFactory {
@Override
public AbstractClient create(String key) {
if ("A".equals(key)) {
return new ClientA();
} else {
return new ClientB();
}
}
}
并将工厂绑定到实现
bind(ClientFactory.class).to(ClientFactoryImpl.class);
AssistedInject对您的情况有害。它提供的所有功能都是自动构建ClientFactoryImpl。该实现仅将注入和辅助参数传递给构造函数。但是在create方法中您有一些平凡的逻辑。在这种情况下,建议您自己创建工厂实现。
答案 1 :(得分:1)
首先,我肯定会同意@Lesiak。代码"strain A25"
不清楚,因为省略号可以是您在ClientA / B上设置的任意多个字段。
但是要给您一个示例,说明如何对您的特定实例使用AssistedInject:
client= new ClientB.Builder()....build();
您的工厂将如下所示:
class ClientA extends AbstractClient {
@Inject
public ClientA(ServiceOne serviceOne,
ServiceTwo serviceTwo,
@Assisted MyObject myObject) {
...
}
}
class ClientB extends AbstractClient {
// Same constructor as ClientA
}
您的参数可以是不同的对象,也可以是您想要的任何对象,但是它们实际上必须与构造函数@Assisted注释匹配。现在您可以看到@Lesiak为何提供他的答案,如果您的构建器在ClientA上设置了10个字段,那么您的工厂方法将需要具有10个方法参数,并且非常不灵活。
然后将其用于:
interface ClientFactory {
@Named("ClientA") public AbstractClient getClientA(...);
@Named("ClientB") public AbstractClient getClientB(...);
}
答案 2 :(得分:0)
假设您要直接创建对象,因此需要使用@Assisted,可以让Guice创建命名工厂:
import javax.inject.Inject;
// com.google.inject:guice:4.2.2
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
// com.google.inject.extensions:guice-assistedinject:4.2.2
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
public class StackOverflow {
public static void main(String[] args) {
final Injector injector = Guice.createInjector(new GuiceModule());
Key<ClientFactory> key = Key.get(ClientFactory.class, Names.named(args[0]));
System.out.println("Client: " + injector.getInstance(key).create("xxx"));
}
}
class GuiceModule extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder().implement(AbstractClient.class, ClientA.class)
.build(Key.get(ClientFactory.class, Names.named("ClientA"))));
install(new FactoryModuleBuilder().implement(AbstractClient.class, ClientB.class)
.build(Key.get(ClientFactory.class, Names.named("ClientB"))));
}
}
abstract class AbstractClient {
}
class ClientA extends AbstractClient {
private String key;
@Inject
public ClientA(@Assisted String key) {
this.key = key;
}
@Override
public String toString() {
return "ClientA [key=" + key + "]";
}
}
class ClientB extends AbstractClient {
private String key;
private Injector injector; // just an example for additional injections
@Inject
public ClientB(@Assisted String key, Injector injector) {
this.key = key;
this.injector = injector;
}
@Override
public String toString() {
return "ClientB [key=" + key + "]";
}
}
interface ClientFactory {
AbstractClient create(String key);
}
这种方法的缺点是,为了使用动态输入,您需要引用Injector,Guice抱怨这很慢-对于您而言,这可能不是问题。如果有人知道如何用更好的方法代替Directjector.getInstance调用,请告诉我!