我有几种数据处理算法可以组装成一个管道来转换数据。代码分为两个部分:执行数据加载相关任务的预处理组件和处理管道组件。
我目前将这两个部分编译并打包成两个独立的罐子。我们的想法是可以将相同的预处理罐运送给所有客户,但可以根据客户要求更换管道罐。我想保持代码简单并最小化配置,以便排除使用OSGi或CDI框架。
通过查看SLF4J的实现,我得到了一些提示。该项目分为两部分:核心API和一堆包装不同日志API的实现。核心API调用虚拟类(它们存在于核心项目中,只是为了允许编译),这些类可以被日志记录项目中的相同类所覆盖。在构建时,在打包到jar之前,已从核心API中删除已编译的虚拟类。在运行时,核心jar和日志jar都需要包含在类路径中,核心jar中缺少的类文件将由日志jar中的文件填充。这样做很好,但对我来说感觉有点笨拙。我想知道是否有更好的设计,或者如果没有使用CDI框架这是最好的。
答案 0 :(得分:1)
听起来像策略软件设计模式。
答案 1 :(得分:0)
示例假设我们有一个服务类型
com.example.CodecSet
旨在表示某些协议的编码器/解码器对的集合。 在这种情况下,它是一个抽象类,有两个抽象方法:public abstract Encoder getEncoder(String encodingName); public abstract Decoder getDecoder(String encodingName);
每个方法返回一个适当的对象,如果提供者有,则返回
的文件null
不支持给定的编码。典型的提供商支持多个 编码。如果com.example.impl.StandardCodecs
是一个实现CodecSet
服务然后它的jar文件还包含一个名为META-INF/services/com.example.CodecSet
此文件包含单行:
com.example.impl.StandardCodecs # Standard codecs
CodecSet
类创建并保存单个服务实例 初始化:private static ServiceLoader<CodecSet> codecSetLoader = ServiceLoader.load(CodecSet.class);
要为给定的编码名称定位编码器,它定义了一个迭代的静态工厂方法 通过已知和可用的提供商,仅在它有时返回 找到合适的编码器或供应商用完。
public static Encoder getEncoder(String encodingName) { for (CodecSet cp : codecSetLoader) { Encoder enc = cp.getEncoder(encodingName); if (enc != null) return enc; } return null; }
getDecoder
方法的定义类似。
您已经明白了如何使用它的要点:
唯一必需的配置文件是打包到.jar文件中的配置文件。
你甚至可以为他们automatically generated添加注释:
package foo.bar; import javax.annotation.processing.Processor; @AutoService(Processor.class) final class MyProcessor extends Processor { // … }
AutoService
将生成文件输出类文件夹中的META-INF/services/javax.annotation.processing.Processor
。该文件将包含:
foo.bar.MyProcessor