What is the best template for managing multiple versions of a single dependency tree in Guice?

I would like to create several versions of the same type of dependency tree / chain that use different implementations for some interfaces in this tree / chain. What is the best practice / guice sample to use in this case?

Here is a concrete example of my problem.

I have a Writer interface that could potentially be a file creator or a std-out creator that will be located on a sheet of my dependency hierarchy. Something like that:

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

Another registrar interface is used to add an indirectness layer to the records. For instance:

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

Then there is a client who uses the registrar.

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

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

  • Client -> LoggerImpl -> FileWriter
  • Client -> LoggerImpl -> StdOutWriter

Is there a good way to connect this device without using a separate Guice module for 1 and 2?

Ideally, I would like to have a ClientFactory class as follows:

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

Can anyone come up with a way to link this with this factory or any other way?

I would also like a solution that scales when I have more variety of longer trees / chains of dependencies. Thanks!

+5
source share
1 answer

This is the problem of the legs of the robot . The solution is basically to use the PrivateModule to bind each dependency tree and expose only the root of that tree. There are several ways to do this, but here is an example of how you usually do it (there are many variations that you can make to suit 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; } ... } 

Your Client fileClient(File) method script is quite a bit different.

+7
source

All Articles