1

ファイルから文字列の配列 (血液検査名のリスト) を (Properties と FileInputStream を使用して) 文字列配列メンバーにロードします。ファイルは文字列を変更できますが、意味は同じままです (たとえば、テストは「abc」と呼ばれ、別の実行では「zzz」と呼ばれます)。テスト名を列挙する列挙型クラスがあります。列挙型文字列は、入力文字列と同じではありません (後者は変更される可能性があるため)。

ファイル Bloodtest.names には以下が含まれます。

bloodTestNames=abc;def;123;

コード:

public enum BloodTestNames {
AAA,BBB,CCC;    
}

Properties props = new Properties();
FileInputStream fis = new FileInputStream("bloodtest.names");
props.load(fis);
String testName[]=props.getProperty("bloodTestNames").toString().split(";");

質問 1: テスト名がわかっている場合、ファイルに設定された文字列を返す必要があります (たとえば、値 BBB に対して "def" を返す)。それをすることの最善は何ですか?

私が思いついた最良の方法は次のとおりです。

return testName[BloodTestNames.BBB.ordinal()]

質問 2: コンパイル時に BBB が不明な場合 - どうすれば同じ目標を達成できますか?

3 つのポイント: * 私は C のベテランですが、Java の初心者です。することもしないことも大歓迎です。私の Java の知識はゼロだとします。* ここで必要なのは完全なリファクタリングではありません。* 重要な詳細について言及するのを忘れている可能性があります。質問してください。不足しているギャップを感じます。

4

3 に答える 3

1

すべての設定を駆動する: statuc メソッドを追加して、どの文字列がどの enum にマップされるかの設定をロードし、これらの設定を使用するファクトリ メソッドを追加します。

public enum BloodTestNames {
    AAA,BBB,CCC; 
    private static Map<String, BloodTestNames> map = new HashMap<String, BloodTestNames>();

    public static void addAlias(String alias, String name) {
        map.put(alias, valueOf(name));
    }

    public static BloodTestNames getByAluas(String alias) {
        if (map.containsKey(alias))
            return map.get(alias);
        // own name assumed to be mapped
        return valueOf(alias);
    }
}

BloodTestNames.addAlias()起動時に、いくつかの設定ファイルに基づいて繰り返し呼び出して、マッピングをロードします。

保存されたファイルを読み取るときBloodTestNames.getByAlias()に、指定された文字列値の列挙型を返すために使用します。


クラスに単数で名前を付け、「名前」を削除することをお勧めします。つまり、BloodTest各列挙型のクラスに名前を付けます(すべての列挙型には、コード化されたインスタンス名である「名前」があります)。

于 2013-06-18T21:38:22.153 に答える
1

最初に、このユースケースをモデル化するために列挙定数が必要であると仮定します。これは、血液検査の種類ごとに実行する特定のコードがあるためです (そうでない場合は、単純な文字列のセットで十分であり、より柔軟です。テストの数を前もって知る必要も、名前を気にする必要もありません)。


Q1: Java 列挙型は値のシーケンスにすぎないため、オブジェクト指向の性質を十分に活用できます。

public enum BloodTest {
    AAA, BBB, CCC;

    private static String[] names;

    public static void setNames(String[] names) {
        if (BloodTest.names != null)
            throw new IllegalStateException("You can only set the names once");
        if (names.length != values().length)
            throw new IllegalArgumentException("Wrong number of names");
        BloodTest.names = names;
    }

    @Override
    public String toString() {
        return names[ordinal()];
    }
}

あとは、enum を呼び出して初期化するだけです。次に、標準メソッドをBloodTest.setNames(namesFromConfiguration)呼び出して、各定数の文字列表現を取得できます。toString()BloodTest.BBB.toString()

最初の前提は、テスト タイプごとに特定のロジックがあることだったので、ロジック (および必要なプロパティ) も enum 自体または enum 定数にカプセル化することをお勧めします。例えば:

public enum BloodTest {
    AAA(10) {
        @Override
        public boolean isRequired(MedicalRecord medicalRecord) {
            return medicalRecord.includes("someDisease");
        }
    },
    BBB(15) {
        @Override
        public boolean isRequired(MedicalRecord medicalRecord) {
            return ! medicalRecord.hasTakenBloodTestsLately();
        }
    },
    CCC(20) { // ... also implements the abstract method and so on

    private final int threshold;

    private BloodTest(int threshold) {
        this.threshold = threshold;
    }

    public boolean hasPassed(int value) {
        return value <= threshold;
    }

    public abstract boolean isRequired(MedicalRecord medicalRecord);

    // ... same as above
}

some への参照を取得したら、対応するメソッドをing なしで呼び出し、ロジックをクライアント コードに分散させることでBloodTest、その特定のテストに合格したかどうかを確認できます。switch

BloodTest bloodTest = BloodTest.valueOf(someString); // someString can be "AAA", "BBB" or "CCC"
// no matter which constant this is, you use it as an object and rely on polymorphism
if (bloodTest.hasPassed(someValue)) { // ... do something

Q2: あなたの質問 2 種類の「質問」は、列挙型の実際の必要性に関する私の最初の仮定です。まだ知らない血液検査を動的に処理する必要がある場合は、列挙型を使用できません。

言い換えれば、コードに各血液検査を処理するためのブロックがまったくない場合、列挙型はユースケースにとって非常に悪い選択ですswitchif/else if

switchただし、そうである場合は、コードをリファクタリングして、上記の例のように/ifブロックではなく列挙型自体にロジックを含めることをお勧めします。さらに、ケースswitchがあるdefault場合 (またはif最終ブロックがある場合)、これは、たとえば定数をフォールバックとしてelse追加することにより、列挙型自体でモデル化できます。DEFAULT

于 2013-06-20T01:10:03.217 に答える