0

我有一个类,我们称之为它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);
    }
}
4

2 回答 2

1

我确实理解了一些完全不同的东西,所以我正在重新编辑这个答案。

我怀疑您正在使用某种导入脚本或其他东西,并且edu.ata.script.data.*您正在编写的是 ClassB、ClassC 等,他们知道如何将内容从一种格式转换为另一种格式......(这只是猜测)

我建议摆脱方法中的所有 if then elseget(String data)是你实现一个责任链。这样,您可以拥有一个链,在 List 中注册几个 edu.ata.script.data.*,然后遍历该列表,直到其中一个为 isType(string) 返回 true,知道您要使用哪个子类处理字符串。

删除isType(String data)方法中的 OR 列表有点棘手,可能这有点过度设计,但您可以执行以下操作:

  1. 在您的类路径中查找可分配的类从您的类

  2. 然后,当您检索您自己可分配的所有类时,您必须通过反射调用每个类的 isType 才能知道结果

    我知道您可能会发现自己对第一点有些迷茫,最好的方法是查看Stripes Framework 中的ResolverUtil类,他们在方法中执行此操作loadImplementationsFromContextClassloader

于 2012-11-28T00:07:01.150 回答
0

看起来您正在尝试将字符串解析为正确子类的实例,方法是将其传递给每个子类的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);
}
于 2012-11-28T01:46:52.360 回答