gpt4 book ai didi

java - 有没有比使用反射通过继承层次结构中的工厂方法实例化元素更好的方法?

转载 作者:行者123 更新时间:2023-11-30 01:48:46 25 4
gpt4 key购买 nike

我构建了一个继承层次结构,其中一堆具体类继承自抽象父类(super class)AA 具有强制属性 String a 和可选 Map b 以及 xml 模型规范的模型元素。 ab 中可能的键值对都是 jaxp.NamedNodeList 的一部分。因此,要设置 ab 的值,我总是需要遍历列表并检查当前属性是否具有名称“id”,并分别设置值对于 a 或将键值对添加到 b。显然,人们希望将其外包给工厂方法等。但是,在抽象父类(super class) A 中实现静态工厂方法显然是不够的,因为通过返回 A 的新实例,我需要在使用工厂创建它时将实例化向下转换为具体元素方法。因此,我想出了一个使用反射的解决方案,但我真的没有安全感,因为没有更简单的方法来解决似乎如此常见的问题。

有没有更简单的解决方案?

这是我的工厂模式,在将 A 向下转换为 B 时导致 ClassCastException SubclassB b = (SubclassB) AbstractSuperClassA.createWith(attributes); :

public static AbstractSuperClassA createWith(NamedNodeMap attributes) {
Map<String, String> attributeMap = new HashMap<>();
String a= null;
for (int i = 0; i < attributes.getLength(); i++) {
if (attributes.item(i).getNodeName().equals("id")) {
a = attributes.item(i).getNodeValue();
}
attributeMap.put(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue());
}
if (a == null) {
// throw RuntimeException
}
return new AbstractSuperClassA (identifier, attributeMap);
}

这是通用反射实现:

public static <T extends AbstractSuperClassA > T init(NamedNodeMap attributes, Class<T> clazz) {
Map<String, String> attributeMap = new HashMap<>();
String a= null;
for (int i = 0; i < attributes.getLength(); i++) {
if (attributes.item(i).getNodeName().equals("id")) {
a = attributes.item(i).getNodeValue();
}
attributeMap.put(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue());
}
if (a== null) {
// throw RuntimeException
}
try {
Constructor<T> constructor = clazz.getConstructor(String.class);
T newElement = constructor.newInstance(a);
newElement.setAttributes(attributeMap);
return newElement;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
log.error(e.getMessage(), e);
}
return null;
}

最佳答案

您的init方法似乎需要一种基于单个String创建给定类的实例的方法值。

在这种情况下,您不需要反射。您可以实现一种“策略模式”形式,而不需要传入Class来实例化和初始化,其中策略是可变的,并且仅定义如何创建新的、ID 初始化的对象。

在 Java 8 及更高版本中,您可以使用函数式接口(interface)和 Lambda 来实现此目的:

private <T extends AbstractSuperClassA > T init(NamedNodeMap attributes, Function<String,T> creator) {
...
T newElement = creator.apply(identifier);
...
}

然后根据需要使用它,例如

B someB = init(attrs, B::new);
C someC = init(attrs, id -> {C c = new C(); c.setId(id); return c;});
...

然而,问题是如何决定应该实例化哪个具体类。在任何情况下,该逻辑都必须在某个地方进行编码,因此可能有更好的方法来连接逻辑以收集值以及初始化新实例。

实例是否需要在构造函数中接收id?或者可以稍后设置吗?

关于java - 有没有比使用反射通过继承层次结构中的工厂方法实例化元素更好的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56836186/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com