java—使用运行时确定的类型创建对象

1dkrff03  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(421)

我正在写一个程序,需要保存和加载文件中的各种对象。文件保存为xml,因此我决定为所有可以转换为xml的类创建一个名为“xmlconvertible”的接口。然而,当我读取文件时,我需要根据xml文件的内容创建不同类型的对象。
例如:

<Component></Component>
<Module></Module>

需要先创建component类型的对象,然后创建module类型的对象。
到目前为止,我遇到的最干净的方法是使用一个工厂,其中包含可从xml文件读取的所有不同类的静态构建器列表。像这样(为了简洁起见,有些信息被省略了):

public interface XMLConvertible {
    public void write();
    public void read();
}

public abstract class Factory {
    private static Map<String, Builder> xmlConvertibles = new HashMap<>();

    public static void addXmlConvertible(String key, XMLConvertible value) {
        xmlConvertibles.put(key, value);
    }

    public static XMLConvertible getXmlConvertible(String key) {
        return xmlConvertibles.get(key);
    }
}

public class Component implements XMLConvertible {
    ...
}

public class ComponentBuilder extends Builder {
    static {
        Factory.addXmlConvertible("Component", new ComponentBuilder);
    }

    public Component build() {...}
}

public class Module implements XMLConvertible {
    ...
}

public class ModuleBuilder extends Builder {
    static {
        Factory.addXmlConvertible("Component", new ComponentBuilder);
    }

    public Module build() {...}
}

问题是,我必须为我添加的每个新xmlconvertible类创建两个类,一个实际类和一个生成器。我想有一种方法强迫自己添加一个构建器,这样我就不会忘记,或者理想地找到一种更干净的方法来实现这样的东西。
很抱歉发了这么长的帖子,我想把它缩短一点。希望还是很容易理解问题所在。

8hhllhi2

8hhllhi21#

您关心xml的格式吗?有像xstream这样的工具可以序列化为xml,例如。

import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.List;

public class Example {

    public static void main(String[] args) {
        XStream xStream = new XStream();

        List<Object> things = new ArrayList<>();
        things.add(new Component("foo"));
        things.add(new Module("bar"));

        String xml = xStream.toXML(things);
        List<Object> things2 = (List<Object>) xStream.fromXML(xml);
    }

    public static class Component {
        private final String componentField;

        public Component(String componentField) {this.componentField = componentField;}
    }

    public static class Module {
        private final String moduleField;

        public Module(String moduleField) {this.moduleField = moduleField;}
    }
}

在pom中,您需要:

<dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.15</version>
        </dependency>

这将产生:

<list>
  <Example_-Component>
    <componentField>foo</componentField>
  </Example_-Component>
  <Example_-Module>
    <moduleField>bar</moduleField>
  </Example_-Module>
</list>

您不需要编写任何特殊的构建器,但是xml文件的结构与类的实现是相同的,因此如果需要任何跨版本兼容性,那么更改可能会很困难。

vptzau2j

vptzau2j2#

最后,我向xmlconvertible接口添加了一个抽象生成器,它将在xmlconvertible的所有实现中被重写。至少这样,我不必为每个新实现创建2个新文件。

public interface XMLConvertible {
    public void write();
    public void read();

    public abstract static class Builder {
        public abstract XMLConvertible build([XML data]);
    }
}

相关问题