【问题标题】:Dependency injection on class with only static methods?只有静态方法的类的依赖注入?
【发布时间】:2013-03-24 14:19:11
【问题描述】:

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


这是我迄今为止的解决方案(通过静态设置方法进行依赖注入)。这是开发人员将使用的公共 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 或子类的实例。
  • 不,这样做的方法不正确。

标签: java design-patterns dependency-injection


【解决方案1】:

您在此处设置的是工厂模式,客户端能够配置工厂返回的实现。这很好,但是您需要做一些不同的事情。

  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()
【解决方案2】:

第 3 方开发人员的最佳解决方案是使用 Proxy 模式。

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

将实现对象设置为实例并不是很好的解决方案。

【讨论】:

    猜你喜欢
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多