web-dev-qa-db-ja.com

複雑なデータ構造を構築しながら、コンストラクターの実行をロールバックするにはどうすればよいですか?

複雑なオブジェクトツリーを構築しています。 ABCD、およびEの合計5つのタイプがあります。ルートノードであるAのインスタンスが1つあります。 Aには1つ以上のBsが子としてあり、各Bには1つ以上のCsが子としてあります。元のデータ形式は、5つの数値(ABCD、およびEの数値ID)とそれぞれに関連付けられるメタデータで構成されるストリームです。

ツリーにある程度のフィルタリングを追加しようとしています。私の現在のアプローチは、入力を取得してAのコンストラクターに渡し、それをBコンストラクトのAsとCコンストラクトのBsにフローダウンすることです。ただし、フィルタリングは最終的にEのレベルで行われます。特定のEのすべてのDが存在しない場合、そのDを作成したくありません。 CDsがない場合、そのCを存在させたくありません。

私の最初の考えは例外をスローすることですが、それはフロー制御に例外を使用しているようです。一部の言語は例外を優先しますが、私は現在Javaで作業しており、例外は例外的な条件になる傾向があります。フィルタが一致しないことは例外的なケースではないと思います。

最終ツリーに子を持つノードのみが含まれ、フィルターが適用されるようにするためのオプションは何ですか?

3
Thomas Owens

これを行うには、データ構造の各レベルでMap<Id, Container>を使用します。コンテナがすでに存在する場合はコンテナを返す、またはまだ存在しない場合は新しいContainerを作成するプライベートヘルパーメソッドを記述します。 これは一般にgetOrAddと呼ばれるメソッドです。

いつものように、基礎となるコンテナがまだ存在していることを確認することは、これを間違えると繰り返しコピーペーストする危険があるボイラープレートコードの束です。代わりに、これを行うために独自のデータ構造を作成する必要があります。または、Guavaを使用して、 Multimap (データの場合に使用できる)を含む多くの便利なツールを提供することができます。構造はかなりばかげています)および ForwardingMap (これにより、すべてのレベルにメタデータがある場合、独自のMap実装を簡単に作成できます)。次に、コンテナがまだ存在しない場合はgetと記述して、 Supplier /Factory(Guavaを使用していない場合)を使用するか、もしそうなら、既存のもの。

2
durron597

まず、コンストラクターで複雑なオブジェクトを作成することは必ずしも良い考えではないことを指摘します。

そうは言っても、それが現在のコードの動作方法であり、それを変更したくない場合は、コンストラクターを軽量ファクトリと交換できるはずです。

A()新しいC()を実行し、それが本当に必要でないと判断する代わりに、ファクトリまたは静的メソッドを使用して実行できます、言語によって異なります):A() C#get()を呼び出すと、Cまたはnullがフィルターで除外された場合に返されます。

3
ptyx