只有静态方法的类如何进行依赖注入?

5

我有一组API类,其中只包含静态方法和一个私有构造函数,因此它们无法被实例化。然而,我希望第三方开发人员能够修改API的行为以适应他们的需求。


这是我目前的解决方案(通过静态setter方法进行依赖注入)。这是开发人员将使用的公共API类。如您所见,它依赖于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();
    }
}

这是我编写的默认API实现。
public class StaticApiImpl {
    public void doThing() {
        System.out.println("Do thing the default way.");
    }
}

这是第三方可能编写的默认实现的假想扩展版本:
public class MyCustomStaticApiImpl extends StaticApiImpl {
    @Override
    public void doThing() {
        System.out.println("Do thing differently.");
    }
}

开发人员只需通过setter方法在插件初始化时注入他们的依赖项即可:
public void onLoad() throws Exception {
    StaticApi.setImpl(new MyCustomStaticApiImpl());
}

我的问题是:这样做是正确的吗?也许有一些专门针对这种情况的设计模式我没有听说过吗?


我会完全删除StaticApi类,并让开发人员注入StaticApiImpl的实例或其子类。 - JB Nizet
不,没有正确的方法来做那件事。 - user2173738
2个回答

2
你的第三方开发者最好使用“代理模式”(Proxy pattern)来解决问题。
参考链接:http://en.wikipedia.org/wiki/Proxy_pattern 将实现对象设置为实例并不是一个很好的解决方案。

2
你在这里建立的是一个工厂模式,客户端可以配置工厂返回哪个实现。这很好,但你需要做一些不同的事情。
  1. StaticApi重命名为StaticApiFactory。这将使其角色更加清晰,并避免与其他部分发生命名冲突。
  2. 删除public static void doSomething()方法。没有必要将所有API方法重新定义为静态方法。因为它是一个工厂类,你只需要一个方法来获取当前的实现,例如一个public static StaticApi getInstance()方法,它返回通过setImpl()设置的实现。
  3. 创建一个接口StaticApi,定义API行为的契约。然后,工厂类应该允许客户端setImpl(StaticApi)
  4. 现在,任何需要使用StaticApi的人都可以通过StaticApiFactory.getInstance()获取引用。

虽然我理解这个答案背后的原因,但它确实会让调用者更加冗长。相比之下,StaticApi.doSomething()StaticApiFactory.getInstance().doSomething() 有很大的对比。 - Peter V. Mørch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接