在Guice中管理同一依赖关系树的多个版本的最佳模式是什么? [英] What is the best pattern for managing multiple versions of the same dependency tree in Guice?

查看:75
本文介绍了在Guice中管理同一依赖关系树的多个版本的最佳模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实例化相同种类的依赖树/链的多个版本,这些版本对树/链中的某些接口使用不同的实现。在这种情况下,最佳的Guice做法/模式是什么?

I would like to instanciate several versions of the same kind of dependency tree/chain which use different implementations for some of the interfaces in that tree/chain. What is the best Guice practice/pattern to use in such case?

以下是我的问题的具体示例。

Here is a concrete example of my problem.

我有一个 Writer 接口,该接口可能是文件编写器或标准输出编写器,它们位于我的依赖关系层次结构的叶子中。像这样的东西:

I have a Writer interface which can potentially be a file writer or a std-out writer, which will be situated at the leaf of my dependency hierarchy. Something like this:

interface Writer { ... }
class FileWriter implements Writer { ... }
class StdOutWriter implements Writer { ... }

另一个记录器接口用于添加一层对作者的间接访问。例如:

Another logger interface is used to add a layer of indirection on the writer. For instance:

interface Logger { ... }

class LoggerImpl{
  @Inject
  public Logger(Writer out){ ... }
  public void log(String message){ out.println(message); }
}

然后有一个使用记录器的客户端。

Then there is a client that uses the logger.

class Client{
  @Inject
  public Client(Logger logger){ ... }
  public void do(){ logger.log("my message"); }
}

现在,我想在程序中使用两种类型的层次结构:

Now, I would like to use two types of hierarchies in my program:


  1. 客户端-> LoggerImpl-> FileWriter

  2. 客户端-> LoggerImpl-> StdOutWriter

是否有一种不错的方法,无需为1和2使用单独的Guice模块将其连接起来?

Is there a nice way of wiring this up without using a separate Guice module for 1 and 2?

理想情况下,我想拥有一个 ClientFactory 类,如下所示:

Ideally I would like to have a ClientFactory class like this:

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

任何人都可以想出一种方法来使用此工厂或通过其他任何方式对此进行连接吗?

Could anyone come up with a way to wire up this using this factory, or by any other means?

我还希望有一种适用于我的情况的解决方案有更多种类的较长的依赖树/链。谢谢!

I would also like a solution that would scale to cases where I have a bigger variety of longer dependency trees/chains. Thanks!

推荐答案

这是机器人腿问题。解决方案基本上是使用 PrivateModule s绑定每个依赖关系树并仅公开该树的根。您可以通过多种方式来执行此操作,但以下是您通常如何执行此操作的示例(您可以根据自己的需要对此进行很多更改):

This is the robot legs problem. The solution is basically to use PrivateModules to bind each dependency tree and expose only the root of that tree. There are several ways you could do this, but here's an example of how you typically might do it (there are a lot of variations on this you can do according to your needs):

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)的方案还是有很大不同。

Your scenario of a method Client fileClient(File) is quite a bit different though.

这篇关于在Guice中管理同一依赖关系树的多个版本的最佳模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆