メモリにデータの複数のビューを保存するにはどうすればよいですか?


8

たくさんのモジュールがあります。これらのモジュールを、完全で重複しないさまざまなカテゴリに分類できます。例えば、3つのように表すことができるIDを持つカテゴリ、AnimalVegetable、およびMineral。さらに、これらのカテゴリをサブカテゴリに分類します。サブカテゴリも、明確で完全であり、重複しません。例えば、のように表すことができるIDS MammalReptileLegumeRootRockGem。最後に、これらのカテゴリの下に、モジュール自体が存在し、例えばCatDogIguanaBeanQuartzEmerald、など

カテゴリー階層

これが私の一般的な使用例です:

  1. すべてのモジュールでさまざまなメソッドを呼び出す必要があります。
  2. すべてのモジュールのすべてのデータの現在の状態のフラットスナップショットを取得する必要があります。
  3. 特定のカテゴリ(サブカテゴリではない)のすべてのモジュールでさまざまなメソッドを呼び出す必要があります。
  4. 既知のIDに基づいて、特定のモジュールでさまざまなメソッドを呼び出す必要があります。
    • これは、「何かをする」または「自分についてのデータを教えて」のいずれかです。
  5. 特定のカテゴリ(サブカテゴリではない)のすべてのモジュールに関する集約データを保存する必要があります。

このデータをどのように保存すればよいですか?

他のいくつかの関連する事実:

  • カテゴリは実行時に確立されます
    • そのため、最下位レベルのモジュールは共通のインターフェースを共有します。
  • いったん設定されると、それらはその特定の実行で変更されません-それらは設定ファイルのデータに基づいています。

これが私が現在していることです:

  1. を含むクラスがありますMap<Category, CategoryDataStructure>。このクラスは、要件#2で使用するためのデータの個別のCollection<Module> ビューも保持します。
  2. CategoryDataStructureを介して、メソッドコールをチェーンに送信するチェーンされた委譲メソッドがありますSubCategoryDataStructure
  3. CategoryDataStructure 要件#5で使用される集計データも格納します。

それは機能しますが、正直なところかなり扱いにくいです。全体はステートフル/ミュータブルであり、変更が困難です。新しい動作を追加したい場合は、多くの場所に追加する必要があります。現在、データ構造自体にも多くのビジネスロジックがあります。委任方法。また、親データ構造は、特定のモジュールと必要に応じてその親データ構造、および必要に応じてその親のデータ構造を作成するために、多くのビジネスロジックを実行する必要があります。

どういうわけか、データ管理ロジックをデータ構造自体から切り離そうとしていますが、ネストが複雑なためです。ここに私が検討してきた他のいくつかのオプションがあります:

  1. シンプルなを作成し、Map<Category, Map<Subcategory, Module>>すべてのコードを配置して、その状態を別のクラスに保持します。これを行う際の私の懸念は要件#1と#2です。同じデータを表す2つの異なるデータ構造があるので、ビューの一貫性を保つのは困難です。
  2. すべてをフラットなデータ構造で実行し、特定のカテゴリまたはサブカテゴリを探す場合は、構造全体をループします。

1つまたは複数のビジターを使用して、「階層内のどのオブジェクトを検査または使用するかを調べる」という責任を分割することを検討しましたか?

@スノーマン私はそのオプションを考慮していません。データをフラットに保存することを提案していますか?次に、メソッドを呼び出す必要があるときにビジターを全員に送信し、handleVisitorクラスで何かが発生する必要があるかどうかを確認していますか?
durron597 2015年

それは少し複雑ですが、答え全体を入力する前に確認したいだけです。

たぶん、トップダウンの構造を反転させてボトムアップで進めることができます。thing.getType()は "Animal"を返します。
名目上の2015年

回答:


6

ここでの中心的な問題は、オブジェクトがアイデンティティに基づいて階層に配置されているが、非階層的な方法で使用していることです。

例えは、ファイルタイプに基づいてファイルをディレクトリに格納することですが、各ディレクトリを検索し、タイプ以外の基準に基づいて特定のディレクトリのみをロードします。


どういうわけか、データ管理ロジックをデータ構造自体から切り離そうとしていますが、ネストが複雑なためです。ここに私が検討してきた他のいくつかのオプションがあります:

これは良い目標であり、大きなリファクタリングなしで責任を分割し始める簡単な方法があります。ビジターを使用します。

階層内の特定の要素のみを検査または操作する必要がある場合、そのロジックをビジター自体に配置するという考え方です。次に、複数の訪問者を記述し、それぞれが異なる要素で動作し、異なるアクションを実行できます。

ロジックの各ユニットは、特定のビジターに自己完結しています。これにより、コードのSRP性が向上します。操作の実行方法を変更する必要がある場合は、そのロジックを実装するビジターでのみ変更できます。オブジェクト階層は、必要なデータを公開するための表面的な変更を除いて、同じままである必要があります。

特定の目標に応じてビジターを実装する方法は複数ありますが、一般的な考え方は、階層内の各ノードがビジターオブジェクトを受け入れることです。その実装は次のようになり、抽象的な親クラスに詰め込むことができます。

public class Node {
  public void accept(Visitor v) {
    v.accept(this);
    for (Node child : children) {
      child.accept(v);
    }
  }
}

これにより、実行時にノードをどのように接続しても、すべてのノードが処理されます。

あなたの訪問者は次のようになります:

public interface Visitor {
  accept(Node n);
}

訪問者のaccept(Node)方法は、実際の作業が行われる場所です。ノードを検査し、条件付きで異なることを行う必要があります(ノードを無視することを含む)。


たとえば、次のことができる場合があります。

Node root = ...;

// Print information on the hierarchy.
root.accept(new DebugVisitor());

// Does stuff with modules, ignores subcategories.
root.accept(new FrobnicateModulesVisitor());

// Eats vegetables, ignores animals and minerals.
root.accept(new EatYourVegetableVisitor());

各ビジターは自己完結型のクラスであり、他のビジターやノードと関係を混在させる必要なく、各操作のロジックが含まれています。


Noteクラスに関する簡単な質問:「子供」はどこで定義されていますか...これは純粋に例示的な例ですか?

@Bey何も定義されていない、それは純粋に例示でした。読者はグラフ理論と木に慣れていると思います。

1

ネストの深いレベルは、returnステートメントを使用してチェーンできる小さな関数にアクションをリファクタリングする必要があることを示唆しています。複数の入力に同じメソッドを適用する必要がある場合はfunction.apply()、Java 8で利用できます。

さまざまなアイテムがプロパティを共有しないと仮定すると、特定のメソッドのセットを実装する必要があるインターフェイスを実装できます。レベルごとに1つのインターフェイスを作成し、それをサブノードごとに拡張します(例:Entity、、PhylumSpecies。さらに、3つのエンティティのそれぞれに3つのクラスが必要です。

データは、オブジェクトインスタンスのプロパティとして保存できます。フラットなスナップショットを作成するには、を使用してデータ全体を反復処理しfunction.apply()ます。


こんにちは、回答ありがとうございます。最下位レベルの要素共通のインターフェースを共有します。これらはすべてランタイムで生成されると言ったときに明確になると思いましたが、その点を明確にするために文を追加するように編集しました。
durron597

次のレベルにもインターフェースが必要なようですが、私は間違っている可能性があります。
名目上の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.