在Guice中管理同一依赖关系树的多个版本的最佳模式是什么?

我想实现同一种依赖树/链的几个版本,它们对该树/链中的某些接口使用不同的实现。 在这种情况下使用的最佳Guice练习/模式是什么?

这是我的问题的一个具体例子。

我有一个Writer接口,它可能是文件Writer器或std-out Writer器,它将位于我的依赖层次结构的叶子中。 像这样的东西:

 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. 客户端 – > LoggerImpl – > FileWriter
  2. 客户端 – > LoggerImpl – > StdOutWriter

有没有一种很好的方法来连接它而不使用单独的Guice模块1和2?

理想情况下,我想有一个像这样的ClientFactory类:

 interface ClientFactory{ public Client stdOutClient(); public Client fileClient(); //or fileClient(File outputFile) for extra points ;) } 

任何人都可以想出一种方法来使用这个工厂,或通过任何其他方式连线?

我还想要一个可以扩展到我有更多种类更长的依赖树/链的情况的解决方案。 谢谢!

这是机器人腿问题。 解决方案基本上是使用PrivateModule绑定每个依赖关系树并仅公开该树的根。 有几种方法可以做到这一点,但这里有一个例子,说明你通常如何做到这一点(你可以根据自己的需要做很多变化):

 public class ClientModule extends PrivateModule { private final Writer writer; private final Class annotationType; public ClientModule(Writer writer, Class 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)方案虽然有点不同。