web-dev-qa-db-ja.com

実行時に変更される可能性のあるモデリングクラス階層

私はさまざまなフィルターを介してドキュメントを処理するアプリケーションを構築しています。

Documentというクラスがあります(または、test-doubleを作成するためのインターフェースとして優れていますか?)。 Documentクラスには多くのフィールドが含まれているため、構築にBuilderパターンを使用することを考えていました。

これで、追加のフィールドを含む特定の「特殊な」ドキュメントがあります(これをSpecialDocumentと呼びましょう)。明白な解決策は、Documentクラスを拡張することです。しかし、どうすれば(実行時に)Documentインスタンスを取得してSpecialDocumentインスタンスにすることができますか? Documentインスタンスの構築は非常に複雑であることを覚えておいてください。したがって、コピーコンストラクターは面倒でエラーが発生しやすい(ファイルを追加するときなど)と思います。

考えられるもう1つの解決策は、元のDocumentインスタンスをSpecialDocumentコンストラクターに渡し、すべてのドキュメント呼び出しをそのインスタンスに委任することです。

または、これらのフィールドをSpecialDocumentからDocumentクラスに追加して、Optional<String> getSpecialFieldのようにオプションのゲッターを提供する必要がありますか?この最後のオプションは、概念が混在しており、クライアントが(最初にオプションを処理する必要があることを除いて)処理するドキュメントの種類がわからないため、最も好ましくないようです。

このシナリオをモデル化する、よりシンプルでエレガントな方法はありますか?

アドバイスありがとうございます。

1
Michael Stadler

オブジェクトのクラスは、オブジェクトのライフサイクル中に変更されることは想定されていません。もしそうなら、設計に問題があるはずです。

あなたが説明する課題の種類は通常、次のように対処されます。

  • デコレータパターン :デコレータSpecialDocumentは、いくつかのメソッド、いくつかのプロパティ、またはその両方など、基本クラスDocumentにいくつかの責任を追加します。
  • エンティティコンポーネントシステム :エンティティDocumentには、一連のプロパティと動作を定義するSpecialDocumentなどのコンポーネントがあります。
  • より高いレベルの抽象化:Documentstrategy が動的に設定してその動作を変更できるように定義されます。

これらの設計パターンの背後にある共通の特徴は、チャンギンクラスの考えが動的にあなたの心と交差するときはいつでも、 継承よりも優先 である構成の創造的な使用です。

6
Christophe

ほとんどの場合私はこれを行います:

class SpecialDocument {
    Document getDocument();
    String getField1();
    String getField2();
}

SpecialDocumentDocumentを拡張せず、リクエストに応じて返されるドキュメントへの参照を含みます。

  1. これにより、複雑なコピーコンストラクターの作成が回避されます。
  2. これにより、一連の委任メソッドの作成が回避されます
  3. これにより、関数が何を必要とするかに応じて、DocumentまたはSpecialDocumentのいずれかを明示的に取ることができます。
1
Winston Ewert