我正在开发一个Java(RCP)项目,我需要将不同的源文件格式(让我们称之为SF-1..N)转换为另外两种不同的目标格式(DF-A,DF-B) 现在输入文件可以是CSV,XLSX和XML(具有不同的模式)。应用程序应找到正确的转换器,并且必须读取文件内容才能执行此操作。 每个转换器规范化文件的内容,并创建DF对象的1..N个实例,这些对象将转换为DF-A或DF-B记录。
所以我有一些转换器获取文件内容并返回DF对象的集合。每个转换器还应该能够判断文件内容是否是它支持的内容。
我能想到的唯一策略是询问每个转换器是否支持文件的内容,以及它是否不尝试下一个。如果没有适合的转换器,则向用户返回错误。
我也可能会被要求添加/支持新格式,我希望能够添加更多转换器,而无需修改不必要的代码。
我正在考虑在服务定位器对象中注册每个转换器,但我不知道如何以最小的耦合来做到这一点。我考虑过在静态初始化程序中注册服务定位器,但只在加载类后才会调用它。
我该怎么做?对于我想要实现的目标,是否有更好的方法?
答案 0 :(得分:2)
M0skit0的答案很好,但鉴于客户端不知道文件的类型,我会让转换器接口实现CanConvert方法。
然后你可以简单地遍历所有转换器,询问是否可以转换文件并使用第一个可以。
这也有一个优点,即您可以动态添加新的转换器而无需更改枚举,因此可以在不重新编译应用程序的情况下添加它们。
答案 1 :(得分:1)
在这种情况下,工厂设计看起来合适
public abstract class DF {
// Default implementation and abstract methods for each subtype
}
public class DF_A extends DF {
}
public class DF_B extends DF {
}
public final enum FileType {
XML, CSV, XLSX;
}
public interface FileConverter {
DF convert(final URI fileLocation);
}
class XMLConverter implements FileConverter {
@Override
public DF convert(final URI fileLocation) {
// Convert file to DF and return DF
}
}
// And so on for all the file type converters
public class FileConverterFactory {
private static Map<FileType, FileConverter> FILE_CONVERTER_MAP = new HashMap<>();
static {
FILE_CONVERTER_MAP.put(FileType.XML, new XMLConverter());
// And so on for all file types
// You can make the map unmodifiable
FILE_CONVERTER_MAP = Collections.unmodifiableMap(FILE_CONVERTER_MAP);
}
public static final DF convert(final FileType fileType, final URI fileLocation) {
return FILE_CONVERTER_MAP.get(fileType).convert(fileLocation);
}
}
如果客户端不知道文件类型,可以按如下方式修改工厂:
public class FileConverterFactory {
private static Map<FileType, FileConverter> FILE_CONVERTER_MAP = new HashMap<>();
static {
FILE_CONVERTER_MAP.put(FileType.XML, new XMLConverter());
// And so on for all file types
// You can make the map unmodifiable
FILE_CONVERTER_MAP = Collections.unmodifiableMap(FILE_CONVERTER_MAP);
}
private static FileType getFileType(final URI fileLocation) throws UnsupportedFileFormatException {
// Check file type and return enum as appropriate
}
// Client knows file type
public static final DF convert(final FileType fileType, final URI fileLocation) {
return FILE_CONVERTER_MAP.get(fileType).convert(fileLocation);
}
// Client doesn't know file type, let factory decide
public static final DF convert(final URI fileLocation) throws UnsupportedFileFormatException {
return convert(getFileType(fileLocation), fileLocation);
}
}