将 class 实现保留在其接口的静态字段中是个坏主意吗?

Is it a bad idea to keep class implementations in a static field of its interface?

我正在做一个项目,我们在接口的静态字段中保留实际的 class 实现。这方面的一个例子是:

public interface Storage {

  public static Storage instance = new DiskStorage();

  public File get(String name) throws Exception;

  public void create(File f) throws Exception;

  public void delete(File f) throws Exception;

}

我们这样做是为了避免使用 IoC 框架的复杂性,并避免像 context.getImpl(Storage.class) 这样的调用使我们的代码乱七八糟。此外,我们这样做也是为了避免引入大型工厂 classes,我们相信我们可以通过在接口的静态字段中保留实现引用来做到这一点。我们由此实现的是,应用程序的任何需要存储内容的部分只需使用 Storage.instance.create(File f).

即可

但是,我们一直在讨论这是否违背了广泛接受的 "principles"。首先;我们是否因为在接口中创建实现依赖而陷入困境?严格来说,接口现在有一个直接 "reference" 到实现。其次,我们意识到我们的测试不能只是 "inject" 一个 MemoryDiskStorage 或一个 MockDiskStorage 作为接口中的静态字段是最终字段。我们如何解决这个问题?

在我看来,您已经回答了自己的问题:是的,这是一个坏主意,因为通过解决 IoC 的复杂性,您已经破坏了 IoC,并且无法在测试中模拟存储实现。这些 context.getImpl(Storage.class) 个电话有一个 原因

它使您无法将接口与实现分开。

例如,在 ModuleA 取决于 ModuleB 的更复杂的应用程序中,您可能希望将 ModuleB 中的服务接口分离到 ModuleBInterface 中,以便 ModuleA 只依赖于 ModuleBInterface。您的方法使这成为不可能,因为接口依赖于实现,而实现又依赖于它的接口。