在运行时交换算法的良好实践或设计是什么?

时间:2015-08-06 17:29:51

标签: java design-patterns

我有几种数据处理算法可以组装成一个管道来转换数据。代码分为两个部分:执行数据加载相关任务的预处理组件和处理管道组件。

我目前将这两个部分编译并打包成两个独立的罐子。我们的想法是可以将相同的预处理罐运送给所有客户,但可以根据客户要求更换管道罐。我想保持代码简单并最小化配置,以便排除使用OSGi或CDI框架。

通过查看SLF4J的实现,我得到了一些提示。该项目分为两部分:核心API和一堆包装不同日志API的实现。核心API调用虚拟类(它们存在于核心项目中,只是为了允许编译),这些类可以被日志记录项目中的相同类所覆盖。在构建时,在打包到jar之前,已从核心API中删除已编译的虚拟类。在运行时,核心jar和日志jar都需要包含在类路径中,核心jar中缺少的类文件将由日志jar中的文件填充。这样做很好,但对我来说感觉有点笨拙。我想知道是否有更好的设计,或者如果没有使用CDI框架这是最好的。

2 个答案:

答案 0 :(得分:1)

听起来像策略软件设计模式。

https://en.wikipedia.org/wiki/Strategy_pattern

答案 1 :(得分:0)

查看ServiceLoader

  

示例假设我们有一个服务类型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方法的定义类似。

您已经明白了如何使用它的要点:

  • 将您的项目拆分为部分(核心,实施1,实施2,......)
  • 使用预处理器发送核心API
  • 让每个实现将正确的META-INF文件添加到其.jar文件中。

唯一必需的配置文件是打包到.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