Java 你会使用DI还是工厂?

Java 你会使用DI还是工厂?,java,spring,Java,Spring,我的应用程序存储文件,您可以选择将文件存储在自己的服务器上或使用S3 我定义了一个接口: interface FileStorage { } 然后我有两个实现,S3FileStorage和LocalFileStorage 在控制面板中,管理员选择所需的FileStorage方法,该值存储在SiteConfiguration对象中 由于可以在应用程序已经运行时更改FileStorage设置,因此您仍然会使用spring的DI来执行此操作吗 或者您会在代码中这样做: FileStorage fs

我的应用程序存储文件,您可以选择将文件存储在自己的服务器上或使用S3

我定义了一个接口:

interface FileStorage {

}
然后我有两个实现,
S3FileStorage
LocalFileStorage

在控制面板中,管理员选择所需的
FileStorage
方法,该值存储在
SiteConfiguration
对象中

由于可以在应用程序已经运行时更改
FileStorage
设置,因此您仍然会使用spring的DI来执行此操作吗

或者您会在代码中这样做:

FileStorage fs = null;

switch(siteConfig.FileStorageMethod)
    case FileStorageMethod.S3:
        fs = new S3FileStorage();

    case FileStorageMethod.Local:
        fs = new LocalFileStorage();
哪一个更有意义


我相信您可以在运行时将DI与spring一起使用,但目前我还没有读到太多关于它的内容。

我仍然会在这里使用依赖注入。如果可以在运行时更改它,则应该使用setter注入而不是构造函数注入来注入它。使用依赖项注入的好处是,您可以轻松地添加接口的新实现,而无需更改实际代码。

我将注入工厂,并让客户端在运行时从工厂请求实际服务。这将使您的客户机与实际的工厂实现分离,因此您也可以有多个工厂实现,例如,用于测试


您也可以使用某种代理对象,其背后有多种策略,而不是工厂,但如果不同的实现无法为来自一个客户端的调用序列(如打开、写入、关闭文件存储)提供服务,则可能会导致问题。

DI毫无疑问。或者,在创建/更新/删除实现时,您是否希望增强出厂代码?在我看来,如果您正在编程一个接口,那么您不应该引导您的实现,不管它实际上有多深

此外,DI并不是Spring等的同义词,它简单到包含一个构造函数,并将抽象接口作为参数,即
public FileApp(FileStorage fs){}


仅供参考,另一种可能性是。

同意。虽然我在下面建议使用DI,但注入工厂也很有效。