3

問題

データをモデル化する最善の方法がわかりません。現在のアプローチが過度に複雑になっているのではないかと心配しており、それを元にコードを作成する前に修正したいと考えています。

モデル化するデータ

50 以上の異なるデータ項目で構成されるデータ セットがあります。各項目は次のとおりです。

  • 一意の識別子int
  • ラベルString.
  • 検証基準 (最小、最大、有効な文字など)。
  • FloatLongIntegerString、またはDate

各項目のラベルと検証基準は、すべてのデータ セットで同じです。 値のみが動的です。順序は重要ではありません。

必要な使用例

データセットにデータを追加する

dataSet.put(itemIdentifier, value);

データ セット内のすべての非 null 値をトラバースして検証する

for (DataItem item : dataSet.values()) {
    boolean valid = item.validate();
    if (valid) {...}
}

指定されたデータ セット内の指定されたアイテムを表示します

public void displayData(List<DataSet> dataSets, int... itemsIdentifiers) {...}

実装の試み

Key私の現在の実装には、マップへの「キー」として抽象クラスがあります。各タイプは、独自の検証ニーズに合わせてサブクラス化されます。次に、DataSetクラス内で、public static各アイテムのキーを持っています。

abstract public class Key {
    public int mId;
    public String mLabel;

    public Key(int id, String label) {...}
    abstract public boolean validate(Object Value);
}

public class FloatKey extends Key {
    private int mMin, mMax;

    public Key(int id, String label, int min, int max) {...}
    public boolean validate(Object Value) {...}
}

// one for each type
...

public class DataSet {
    public static Key ITEM_A = new FloatKey(1, "item A", 0, 100);
    public static Key ITEM_B = new DateKey(2, "item B", "January 1, 1990");
    // ~50 more of these

    private Map<Key, Object> mMap;

    public void put(int itemId, Object value) {...}
    public Set<Object> values() {...};
    ...
}

から値を取り出すときに、DataSetのようなことができるように、値とキーを保持する必要があるのは好きではありませんDataSet.ITEM_A.validate(someFloat)instanceofまた、状況によってはサブクラスのみのメソッドを呼び出す必要があるため、セット内のオブジェクトをトラバースするときに頻繁に使用およびキャストしていることに気付きます。


さらに明確にするための編集

  • データ項目とその検証基準は時折変更する必要があるため、メンテナンスは比較的簡単/無痛でなければなりません。

  • オブジェクト自体をキーとしてマップに使用することもできますが、KeyこれらのキーをBundle(Android API の一部) に配置する必要がある場合があります。labelまたはid(ラベルが同じ場合) を使用して、Keyクラスを作成しないようにしParcelableます。

4

2 に答える 2

1

このアプローチはどうですか: このインターフェースを作成します:

interface Validable {
    boolean isValid();
}

次に、すべてのデータ項目は次のクラスを継承し、暗黙的にインターフェイス ::

abstract class DataItem implements Validable {

    public DataItem(int id, String label, int min, int max) {
    }
}

コンストラクター パラメーターを介して DataItem の特定の各インスタンスを構成し、共通の値と個別の値を渡します。

class FloatItem extends DataItem {

    public FloatItem(int id, String label, int min, int max, Float value) {
        super(id, label, min, max);
        // set the Float value here
    }

    @Override
    public boolean isValid() {
        // validate here
        return true;
    }
}

class DateItem extends DataItem {

    public DateItem(int id, String label, int min, int max, Date value) {
        super(id, label, min, max);
    }

    @Override
    public boolean isValid() {
        // validate here
        return true;
    }
}

クライアント コードは、次のようにオブジェクトを組み立てます::

List<Validable> items = Lists.<Validable>newArrayList(new FloatItem(0, "", 0, 0, Float.NaN),
            new DateItem(0, "", 0, 0, new Date()));

(Google Guava の使用に注意してください)

呼び出しコードはこれを行うだけです::

for (Validable validable : items) {
    System.out.println(validable.isValid());
}

このアプローチでは、最初に「ターゲット」オブジェクトを作成してから、それらが有効かどうかを質問する必要があることに注意してください。つまり、コンストラクターを介して有効なパラメーターを渡し、オブジェクトが有効かどうかを尋ねます。オブジェクト自体は、その内部の検証基準を使用して質問に答えます...問題を正しく理解できたことを願っています。

于 2013-10-10T17:44:57.933 に答える