Dependency injection on class with only static methods?
dependency-injection, design-patterns, java
Solution
What you are setting up here is a factory pattern with the ability for clients to configure which implementation the factory returns. That is fine, but there are a couple of things that you need to do differently.
- Rename `StaticApi` to `StaticApiFactory`. This will make its role more clear and avoid a naming conflict with the next parts.
- Remove the `public static void doSomething()` method. There's no need to redefine all of your API methods as static methods. Since that is a factory class, all you need instead is a method to get the current implementation, e.g. a `public static StaticApi getInstance()` method that returns the implementation that has been set via `setImpl()`.
- Create an interface `StaticApi` that defines the contract of the APIs behavior. The factory class should then allow the clients to `setImpl(StaticApi)`.
- Now anyone that needs to use the StaticApi can get a reference via `StaticApiFactory.getInstance()`.
Problem
I have a set of API classes which contain only static methods and a single private constructor so they cannot be instantiated. However, I would like a third party developer to be able to modify the behaviour of the API's to suit their needs. This is the solution I have so far (dependency injection via static setter method). This is the public API class that the developer would use. As you can see, it has a dependency on `StaticApiImpl`. ``` public class StaticApi { private static StaticApiImpl impl = new StaticApiImpl(); private StaticApi() {} public static void setImpl(StaticApiImpl impl) { StaticApi.impl = impl; } public static void doThing() { impl.doThing(); } } ``` This is the default API implementation as coded myself. ``` public class StaticApiImpl { public void doThing() { System.out.println("Do thing the default way."); } } ``` This is a hypothetical extended version of the default implementation that a third party might write: ``` public class MyCustomStaticApiImpl extends StaticApiImpl { @Override public void doThing() { System.out.println("Do thing differently."); } } ``` The developer would then simply inject their dependency via the setter method upon initialisation of their plugin: ``` public void onLoad() throws Exception { StaticApi.setImpl(new MyCustomStaticApiImpl()); } ``` My question is: is this the correct way of doing it? Is there perhaps some design pattern dedicated to cases such as this that I have not heard of?