我想实现同一种依赖树/链的几个版本,它们对该树/链中的某些接口使用不同的实现。在这种情况下使用的最佳Guice练习/模式是什么?
以下是我的问题的具体示例。
我有一个Writer
接口,可能是文件编写器或std-out编写器,它位于我的依赖层次结构的叶子中。像这样:
interface Writer { ... }
class FileWriter implements Writer { ... }
class StdOutWriter implements Writer { ... }
另一个记录器接口用于在writer上添加一个间接层。例如:
interface Logger { ... }
class LoggerImpl{
@Inject
public Logger(Writer out){ ... }
public void log(String message){ out.println(message); }
}
然后有一个使用记录器的客户端。
class Client{
@Inject
public Client(Logger logger){ ... }
public void do(){ logger.log("my message"); }
}
现在,我想在我的程序中使用两种类型的层次结构:
是否有一种很好的方法可以在不使用1和2的单独Guice模块的情况下进行连接?
理想情况下,我希望有一个ClientFactory
类,如下所示:
interface ClientFactory{
public Client stdOutClient();
public Client fileClient();
//or fileClient(File outputFile) for extra points ;)
}
有人能想出一种方法来使用这个工厂或任何其他方式连接它吗?
我还想要一个可以扩展到我有更多种类更长的依赖树/链的情况的解决方案。谢谢!
答案 0 :(得分:7)
这是robot legs问题。解决方案基本上是使用PrivateModule来绑定每个依赖关系树并仅公开该树的根。有几种方法可以做到这一点,但这里有一个例子,说明你通常如何做(根据你的需要你可以做很多变化):
public class ClientModule extends PrivateModule {
private final Writer writer;
private final Class<? extends Annotation> annotationType;
public ClientModule(Writer writer, Class<? extends Annotation> annotationType) {
this.writer = writer;
this.annotationType = annotationType;
}
@Override protected void configure() {
bind(Writer.class).toInstance(writer);
bind(Logger.class).to(LoggerImpl.class);
expose(Client.class).annotatedWith(annotationType);
}
}
public class ClientFactoryModule extends AbstractModule {
private final File file;
public ClientFactoryModule(File file) {
this.file = file;
}
@Override protected void configure() {
install(new ClientModule(new StdOutWriter(), StdOut.class));
install(new ClientModule(new FileWriter(file), FileOut.class));
bind(ClientFactory.class).to(ClientFactoryImpl.class);
}
}
public class ClientFactoryImpl implements ClientFactory {
private final Client stdOutClient;
private final Client fileClient;
@Inject public ClientFactoryImpl(@StdOut Client stdOutClient,
@FileOut Client fileClient) {
this.stdOutClient = stdOutClient;
this.fileClient = fileClient;
}
...
}
方法Client fileClient(File)
的方案虽然有点不同。