Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 单一责任原则与DI接口的正确组织方式_Java_Oop_Inheritance_Dependency Injection_Interface - Fatal编程技术网

Java 单一责任原则与DI接口的正确组织方式

Java 单一责任原则与DI接口的正确组织方式,java,oop,inheritance,dependency-injection,interface,Java,Oop,Inheritance,Dependency Injection,Interface,假设您有存储在磁盘上的文件,您需要加载它们。文件有3种类型,扩展名分别为*.ext1、*.ext2和*.ext3。因此,我有三个load方法,每个方法都应该通过不同的锁进行同步。我应该用DI框架将这种行为注入到我的服务中。以下哪种方法更好 第一种方式似乎是显而易见的。但让我不确定的是,单一责任的原则以及您永远不想加载所有三个扩展的事实:您将只加载1&3或2&3 1)所有文件类型加载程序的通用界面: 2)每种文件类型的特定接口: 3)接口层次结构: 4)单一接口: 定义一个工厂类以提供通用加载函数

假设您有存储在磁盘上的文件,您需要加载它们。文件有3种类型,扩展名分别为
*.ext1
*.ext2
*.ext3
。因此,我有三个
load
方法,每个方法都应该通过不同的锁进行同步。我应该用DI框架将这种行为注入到我的服务中。以下哪种方法更好

第一种方式似乎是显而易见的。但让我不确定的是,单一责任的原则以及您永远不想加载所有三个扩展的事实:您将只加载1&3或2&3

1)所有文件类型加载程序的通用界面:

2)每种文件类型的特定接口:

3)接口层次结构:

4)单一接口:

  • 定义一个工厂类以提供通用加载函数,如

    公共类文件加载器{

    //定义一个类似于

    私有映射扩展加载映射

    公共静态文件加载(StringfilePath){

    //从地图中提取扩展并获取适当的加载程序

    //在这里做些有意义的事情

    }

  • 定义一个接口,比如

    公共接口扩展加载程序{

    公共文件加载扩展名(字符串文件路径)

    }

  • 现在您可以定义尽可能多的扩展加载程序

  • 您可以使用DI框架存储所有这些映射,如spring框架所述


  • 这将使您能够添加/修改扩展加载器的功能,而无需修改实际文件加载器的java代码。

    第三种解决方案看起来是这里最明智的解决方案。但添加不起任何作用的标记接口似乎过于工程化

    我建议你考虑我对你的任务的看法:

    public interface FileLoader {
        void load();
    }
    
    只有一个接口,实现将显示加载特定格式的文件。每个加载程序都有一个唯一的名称,用于描述加载程序将使用的文件类型

    @Component("Ext1")
    public class Ext1FileLoader implements FileLoader {
        public synchronized void load() {}
    }
    
    之后,我们需要一家按需生产装载机的工厂

    @Component
    public class FileLoaderFactory implements ApplicationContextAware {
    
        // to get new loaders
        private ConfigurableApplicationContext context;
    
        // to keep already pulled out instances
        private Map<String, FileLoader> loaders;
    
        public FileLoader getFileLoaderByFileType(String type) {
            // trying to use a lazy-loading mode
    
            return loaders.get(type) == null ? getFromContext(type) : loaders.get(type);
        }
    
        private FileLoader getFromContext(String type) {
            // getting a bean from the context, putting it into a map and returning a value
    
            FileLoader loader = context.getBean(type, FileLoader.class);
            loaders.put(type, loader);
            return loader;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext context) throws BeansException {
            // a casting here is to get broader functionality from a context instance
    
            this.context = (ConfigurableApplicationContext) context;
        }
    
    }
    
    @组件
    公共类FileLoaderFactory实现ApplicationContextAware{
    //买新的装载机
    私有配置应用程序上下文上下文;
    //保留已拉出的实例
    私人地图加载器;
    公共文件加载程序getFileLoaderByFileType(字符串类型){
    //尝试使用延迟加载模式
    返回loaders.get(type)==null?getFromContext(type):loaders.get(type);
    }
    私有文件加载程序getFromContext(字符串类型){
    //从上下文获取bean,将其放入映射并返回值
    FileLoader=context.getBean(类型,FileLoader.class);
    装载机。放置(类型,装载机);
    返回装载机;
    }
    @凌驾
    public void setApplicationContext(ApplicationContext上下文)引发BeansException{
    //这里的转换是从上下文实例获得更广泛的功能
    this.context=(ConfigurableApplicationContext)上下文;
    }
    }
    

    下面的解决方案可能更简洁,但我们无法打开惰性初始化模式。请看:

    @组件
    类FileLoaderFactory{
    //它将收集内容中所有可用的加载程序
    私有@Autowired地图加载器;
    公共文件加载程序getFileLoaderByFileType(字符串类型){
    返回装载机。获取(类型);
    }
    }
    
    你为什么不直接使用
    文件加载程序
    界面,将
    Ext1Loader
    作为实现呢?@RolandIllig请看第四种方法,我忘了介绍it@V_B,您是否有
    FileExt1
    FileExt2
    类或某些文件层次结构?@AndrewTobilko否,我只需要将这些文件解析为
    Map
    。这些文件的格式非常简单,不需要单独的文件类层次结构。您使用的DI框架是什么?我可以用Spring提供我的观点吗?提示:在编写源代码时,请确保它的格式正确为源代码!如果您不知道如何工作,请更好地研究有关标记的帮助!提示2:列表中的代码需要双ind要正确设置格式,请单击entation。
    //This makes me feel like all implementations `Ext1Loader`, `Ext2Loader` and `Ext3Loader` are interchangable. 
    //But actually you may want to inject `Ext1Loader` nad `Ext3Loader` simultaneously into your class
    public interface FileLoader { public void load(); }
    public class Ext1Loader implements FileLoader { public synchronized void load() { /* impl */ } }
    public class Ext2Loader implements FileLoader { public synchronized void load() { /* impl */ } }
    public class Ext3Loader implements FileLoader { public synchronized void load() { /* impl */ } }
    
    public interface FileLoader {
        void load();
    }
    
    @Component("Ext1")
    public class Ext1FileLoader implements FileLoader {
        public synchronized void load() {}
    }
    
    @Component
    public class FileLoaderFactory implements ApplicationContextAware {
    
        // to get new loaders
        private ConfigurableApplicationContext context;
    
        // to keep already pulled out instances
        private Map<String, FileLoader> loaders;
    
        public FileLoader getFileLoaderByFileType(String type) {
            // trying to use a lazy-loading mode
    
            return loaders.get(type) == null ? getFromContext(type) : loaders.get(type);
        }
    
        private FileLoader getFromContext(String type) {
            // getting a bean from the context, putting it into a map and returning a value
    
            FileLoader loader = context.getBean(type, FileLoader.class);
            loaders.put(type, loader);
            return loader;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext context) throws BeansException {
            // a casting here is to get broader functionality from a context instance
    
            this.context = (ConfigurableApplicationContext) context;
        }
    
    }
    
    @Component
    class FileLoaderFactory {
    
        // it would collect all loaders available in the content
        private @Autowired Map<String, FileLoader> loaders;
    
        public FileLoader getFileLoaderByFileType(String type) {
            return loaders.get(type);
        }
    
    }