A ServiceLoader
can be used to dynamically choose an implementation for a specific interface (or abstract class) - called a Service
.
This has the advantage that any client of your library can supply a service implementation in a decoupled way. You do not need to worry about the specific class to instantiate or use. Just make sure some jar on the classpath provides it.
See Simple plugin systems via ServiceLoader’s for an example usage of this pattern.
One characteristic of this approach is the registration of your service implementation inside a file in the META-INF/services
folder.
This file has to have the name of the service and contain the fully qualified name of your implementation.
After writing tons of these files manually at detekt, I’ve come up with a IntelliJ-Plugin to automate this repetitive work.
It defines an Action
(Ctrl+Shift+A) Generate MetaInf Service Entry which uses the qualified name of the current opened class as the implementation name.
The name of the first extended super type will be used as the service name.
Note: it is just a very simple plugin, handles no edge cases and does no additional checks.
If you may need to provide more than one implementation for the same service interface and/or your package structure changes a lot, you may find AutoService helpful. It is an annotation processor which generates service files based on annotations at compile time.