简体   繁体   中英

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?

The best solution for your 3rd party developer will be using the Proxy pattern.

http://en.wikipedia.org/wiki/Proxy_pattern

Setting the implementation object as instance is not great 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.

  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, eg 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() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM