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