Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection on class with only static methods?

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?

like image 841
Phil K Avatar asked Oct 04 '22 15:10

Phil K


1 Answers

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.

  1. Rename StaticApi to StaticApiFactory. This will make its role more clear and avoid a naming conflict with the next parts.
  2. 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().
  3. Create an interface StaticApi that defines the contract of the APIs behavior. The factory class should then allow the clients to setImpl(StaticApi).
  4. Now anyone that needs to use the StaticApi can get a reference via StaticApiFactory.getInstance().
like image 192
Blake Avatar answered Oct 13 '22 12:10

Blake