如何使用 YAML 配置文件使用对象参数实例化新对象?

2024-01-23

我试图使用配置文件来允许用户选择实现某些抽象类或接口的具体聚类算法。每种算法的先决条件输入可能略有不同。一个小的概念示例:

  • KMedoids只需要拥有k由用户设置。
  • SpectralClustering还需要k但还需要其他一些东西,例如Enums 代表图的类型,以及在其内部计算中使用的拉普拉斯算子的类型。

两者的共同点都定义在一个抽象类中。

为了使事情更普遍,我编了一个虚拟的例子。假设我有一个Configuration将传递给某种“引擎”或“驱动程序”以完成基于实例的作业的类Configuration生成的。

public class Configuration {

    private AbstractAlgorithm algo;
    private AbstractParameter param1;
    private ConcreteEnum.Enum1 param2;
    private ConcreteEnum.Enum2 param3;
   
    // getters and setters...

然后我就上课了

abstract class AbstractAlgorithm{
    AbstractParameter abstractParam;
    public void setParam(AbstractParam p) {
        this.abstractParam = p;
    }

    public RandomObject runAlgo(DataObject data);
}

and ConcreteAlgorithm:

public class ConcreteAlgorithm extends AbstractAlgorithm {

    ConcreteEnum.enum1 concreteParam1;
    ConcreteEnum.enum2 concreteParam2;

    public ConcreteAlgorithm(ConcreteParameter p1, ConcreteParameter p2) {
        this.concreteParam1 = p1;
        this.concreteParam2 = p2;
    }

    public abstract void runAlgo(DataObject data) {
        if (abstractParam == null) {
            throw new IllegalStateException();
        } else {
        // do calculations based on enums and abstractParam value
        }
    }

那么我的问题是:伴随的将如何.yaml文件查找以便可以将其解析为实例化的Configuration可以传递给使用它的对象吗?


与序列化一样,您的类应该有一个不带参数的构造函数:

abstract class AbstractAlgorithm {
    public AbstractParameter abstractParam;
}

public class ConcreteAlgorithm extends AbstractAlgorithm {
    public ConcreteEnum.Enum1 param1;
    public ConcreteEnum.Enum2 param2;
}

除了字段之外,无论它们有什么接口,都与这个问题无关。我将这些字段公开,因为当您进行反序列化时,它们没有真正的意义,除非您想在设置器中处理给定的值,在这种情况下您将使用设置器。

现在定义了这些类型,加载将按如下方式进行:

Constructor constructor = new Constructor();
constructor.addTypeDescription(
    new TypeDescription(ConcreteAlgorithm.class, new Tag("!concrete")));
yaml = new Yaml(constructor);
AbstractAlgorithm = yaml.loadAs(someInput, AbstractAlgorithm.class);

正在加载的 YAML 看起来像这样:

--- !concrete
abstractParam: spam
param1: egg
param2: sausage

The --- is the 指令结束标记,它开始文档的内容并且是可选的。我们在这里使用它是为了明确以下标记适用于文档的根节点。

!concrete是根节点的标签。由于我们使用 SnakeYAML 注册它,因此它将导致 SnakeYAML 从该文件构造一个 ConcreteAlgorithm 对象。

以下键值对为 ConcreteAlgorithm 的每个字段(包括继承的字段)提供值。 SnakeYAML 将根据所使用的类的性质处理字段值 –AbstractParameter如果它是一个类,可能希望在 YAML 文件中具有嵌套映射。如果AbstractParameter是另一个抽象类并且有ConcreteParameter作为实施,你会做

--- !concrete
abstractParam: !cp
  droggel: jug
param1: egg
param2: sausage

并注册!cp作为标签ConcreteParameter。包含键的嵌套映射droggel然后会生成一个实例ConcreteParameter并被分配到该字段abstractParam.

由于您可以在任何级别上提供标签,因此您可以在将 YAML 加载到的结构中的任何位置嵌套具有抽象类类型的字段。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 YAML 配置文件使用对象参数实例化新对象? 的相关文章

随机推荐