0

私は 1 つのクラスを持っていClassAます。ClassA、およびその下のすべてのクラスStringは、コンストラクターの引数に at を取ります。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 else を取り除くための私の提案は、責任の連鎖get(String data)を実装することです。そうすれば、いくつかの edu.ata.script.data.* をリストに登録するチェーンを持つことができます。次に、それらのいずれかが isType(string) に対して true を返すまで、使用するサブクラスを認識して、そのリストを反復処理します。文字列を処理します。

メソッド内の OR のリストを削除するのはisType(String data)少しトリッキーで、おそらくこれはエンジニアリングが少し過剰ですが、次のようにすることができます。

  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 に答える