我有一个类,我们称之为ClassA
,还有它的一堆子类,以及这些类的后续子类。ClassA
,以及它下面的每个类在其构造函数中的一个参数处接受一个String
。我有一堆String
对象,需要将它们"转换"为ClassA
的子类。
我目前使用的方法是isType(String)
方法,该方法检查String
是否是该子类的实例,但使用一个巨大的if-else或switch-case语句来查找ClassA
的正确类型(即String
)似乎是一种非常糟糕的编程技术。是否有一种常见的方法来遍历子类结构,或者我一直使用的方法可以吗?
这样做的目的是,我正在制作一种脚本语言(为了一个有趣的项目),我需要能够识别什么是什么
示例代码:
public static boolean isType(String data) {
data = data.trim();
return edu.ata.script.data.Boolean.isType(data)
|| edu.ata.script.data.Integer.isType(data)
|| edu.ata.script.data.Double.isType(data)
|| DATA_STORAGE.contains(data)
|| ReturningMethod.isType(data)
|| edu.ata.script.data.String.isType(data);
}
public static Data get(String data) {
data = data.trim();
/*:)*/ if (edu.ata.script.data.Boolean.isType(data)) {
return edu.ata.script.data.Boolean.get(data);
} else if (edu.ata.script.data.Integer.isType(data)) {
return edu.ata.script.data.Integer.get(data);
} else if (edu.ata.script.data.Double.isType(data)) {
return edu.ata.script.data.Double.get(data);
} else if (DATA_STORAGE.contains(data)) {
return (Data) DATA_STORAGE.get(data);
} else if (ReturningMethod.isType(data)) {
return ReturningMethods.getMethodValue(data);
} else if (edu.ata.script.data.String.isType(data)) {
// Last option because everything is accepted.
return edu.ata.script.data.String.get(data);
} else {
throw new RuntimeException("Could not parse data - " + data);
}
}
我确实理解了一些完全不同的东西,所以我正在重新编辑这个答案。
我怀疑你正在使用某种导入脚本或其他东西,edu.ata.script.data.*
是你正在编写的ClassB、ClassC等,他们知道如何将内容从一种格式转换为另一种格式。。。(这只是猜测)
我建议去掉get(String data)
方法中的所有if-then-else,那就是实现一个响应链。这样,你就可以有一个在List中注册几个edu.ata.script.data.*的链,然后你在该列表中迭代,直到其中一个对isType(字符串)返回true,知道你想用哪个子类来处理字符串。
在isType(String data)
方法中删除OR列表有点棘手,可能这有点过于复杂,但您可以执行以下操作:
-
在类路径中查找可从类分配的类
-
然后,当您检索所有可由自己分配的类时,您必须通过反射调用每个类的isType才能知道结果
我知道你可能会发现自己对第一点有点迷失,最好的方法是从Stripes Framework中查看ResolverUtil类,他们在方法
loadImplementationsFromContextClassloader
中这样做
看起来你正试图将一个字符串解析为正确子类的实例,方法是将其传递给每个子类的isType
方法,直到有人说它可以处理它。我会让每个子类注册一个解析器对象,该对象可以检查字符串,并在可能的情况下生成相应子类的初始化实例。
解析器接口:
package edu.ata.script.data;
interface ScriptParser {
public boolean isType(String data);
public Data get(String data) throws UnparsableException;
}
数据子类示例:
package edu.ata.script.data;
public class Boolean extends Data {
// Empty constructor for reflection purposes
public Boolean() {};
public Boolean(String data) {
// Initialise from string
}
public ScriptParser getParser() {
return new ScriptParser() {
public boolean isType(String data) {
return "true".equals(data) || "false".equals(data);
}
public Data get(String data) throws UnparsableException {
if (isType(data)) {
return new edu.ata.script.data.Boolean(data);
} else {
throw new UnparsableException(data);
}
}
};
}
}
然后,您可以在解析之前将类列表构建到集合中:
List<ScriptParser> parsers = new LinkedList<>();
parsers.add(new edu.ata.script.data.Boolean().getParser());
parsers.add(new edu.ata.script.data.Integer().getParser());
parsers.add(new edu.ata.script.data.Double().getParser());
...
上述也可以通过反射来实现。
然后,无论最终支持多少数据类型,您都可以使用一个简单的循环来解析数据:
public Data get(String data) throws SyntaxErrorException {
for (ScriptParser sp:parsers) {
if (sp.isType(data)) {
try {
return sp.get(data);
} catch (UnparsableException e) {
// This shouldn't happen, but better safe than sorry!
e.printStackTrace();
}
}
}
throw new SyntaxErrorException(data);
}