コンポジットデザインパターンを使用する必要がある場合がわかりません。 このデザインパターンからどのようなメリットが得られますか?私が訪問しました このWebサイト 中古。設計パターンを学び始めている私のようなプログラマーにとって有益であることを願っています。
デザインパターン から引用
次の場合に複合パターンを使用します
- オブジェクトの部分全体の階層を表現したい場合。
- クライアントがオブジェクトの構成と個々のオブジェクトの違いを無視できるようにする必要があります。クライアントは、複合構造内のすべてのオブジェクトを均一に扱います。
一般的な使用法は、本のやる気を起こさせる例として使用されているもので、他のウィンドウや画像、テキストなどのグラフィック要素を含むことができるグラフィックウィンドウの表示システムです。コンポジットは実行時に構成でき、クライアントコードは、描画などの一般的な操作のためにどのタイプであるかを気にすることなく、すべての要素を操作できます。
コンポジットは、実際には異なる場合でも、階層の一部であるオブジェクトのグループを「同じ」として選択的に処理する必要がある場合に便利なパターンです。通常、使用される例ではリーフとノードを同じように扱うという点で説明しますが、パターンを異種リストに拡張することもできます。
たとえば、医師の診察を考えてみましょう。医者に行くとさまざまなことが起こります。通常、まず看護師や助手に会い、体温を測ります。その後、医者は検査を行い、診断を下します。その後、医師が何らかの治療を行う場合がありますが、多くの場合、看護師は戻って終了します。また、訪問中にさまざまな活動が行われます。体重や体温などの観察結果があります。しかし、たとえばラボは別のオブジェクトになります。多くの場合、サンプルは後で送信され、結果を後日記録する必要があるためです。
そのため、このすべてを記録できるソフトウェアがあり、通常は次のようなノードで何らかの階層を作成します。
出会い:
PreExam
試験
処理
そして、これらの各ノードの下には、診断、観察、検査手順、診断、注入などのさまざまなエントリがあります。
これはすべて順調であり、非常に複雑な階層的な記録であるにも関わらず、最終的に構造化されます。
ここで、請求書を生成する必要があるとします。突然、非常に異なる要件に直面します。あなたの医療記録は、出会いの非常に正確な写真を作成するために必要でした。課金では、誰がどのような順序で実行したかは気にしませんが、実際には、請求コードを超えたアクティビティが何であるかは気にしません。課金可能なアクティビティの単一のリスト、つまりコードが必要です。
この情報はレコードに埋め込まれているだけでなく、そのレコードには多数の異なるオブジェクトが含まれているため、走査が非常に困難です。また、階層構造も異なります。頭に爪がある場合、あらゆる種類の事前試験やその問題の試験をスキップして治療を受けることができます。ステッチを削除する場合は、事前試験や試験がない場合があります。毎年の物理的な治療はありません。など。この種のオブジェクトグラフを列挙するのは非常に困難です。
複合パターンはこれをすべて解決します。すべてのオブジェクトに共通のインターフェースまたは基本クラスを定義します。それを「CareEntry」と呼びましょう。 CareEntryには、プロパティBillingCodeがあります。これで、EncounterはCareEntryオブジェクト以外は何もない単純なコンテナのように見えるようになります。課金サービスは、ノード(PreExam、Exam)とリーフ(重量温度)、オブジェクトのあるノード(PreExam Examなど)や実際のタイプを気にすることなく、内部のすべてを単純に列挙できるようになりました。オブジェクトの(ラボ、注入など)です。すべてがCareEntryでもあり、均一に扱われます-Encounter内のすべてのCareEntryオブジェクトを列挙し、null以外の請求コードを持つ各オブジェクトを収集するだけです。それはそれと同じくらい簡単です。
複合パターンを使用すると、クライアントは個々のオブジェクトと(個々のオブジェクトの)構成を均一に処理できます。
たとえば、フォルダをダブルクリックすると、フォルダが開かれます。ファイルの2倍では、対応するプログラムで開く必要があります。
操作は同じですが、個々のオブジェクトまたは構成のどちらであるかに基づいて動作します
個々のオブジェクトと複合オブジェクトの共通インターフェース
interface Data{
public void doubleClick();
}
個別オブジェクトの実装
class File implements Data {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void doubleClick() {
System.out.println(this.getName()+" file is Opened in a Program ");
}
}
複合実装
class Folder implements Data {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private List<Data> folder = new ArrayList<Data>();
@Override
public void doubleClick() {
System.out.println(this.getName() + " folder is Opened");
for(Data data : folder) {
data.doubleClick();
}
}
public void add(Data data) {
folder.add(data);
}
public void remove(Data data) {
folder.remove(data);
}
}
クライアントプログラム
public class CompositePattern {
public static void main(String[] args) {
Folder f1 = new Folder();f1.setName("Folder 1");
Folder f2 = new Folder();f2.setName("Folder 2");
Folder f3 = new Folder();f3.setName("Folder 3");
File file1 = new File();file1.setName("File 1");
File file2 = new File();file2.setName("File 2");
File file3 = new File();file3.setName("File 3");
File file4 = new File();file4.setName("File 4");
f1.add(file1);
f2.add(file2);
f3.add(f2);
f3.add(file3);
f3.add(file4);
f1.doubleClick();f2.doubleClick();f3.doubleClick();
}
}
私はよく、複合デザインパターンを使用してコレクションを非表示にします。多くの場合、多くの要素があり、要素が1つしかない場合、コレクションをまったく同じように操作します。
これは問題です。コレクションを含むクラスは、基本的に同じことを行うforeachループで群がるので、すべての要素を調べて、集計関数を適用します。
この問題を解決するために、単一の要素とそれらの要素のコレクションを隠すクラスによって実装されるインターフェースを導入します。複合クラスの目的は、クライアントクラスにあったすべての集計関数を含めることです。
この記事でいくつかの便利な例を見つけることができます: Working With Collections
ここでの一般的なことは、Compositeは必ずしも部分全体の関係を表すとは限らないということです。クライアントからループを移動するためだけに複合要素を導入することができます。
そして、複合要素の背後にある部品を隠すために複合パターンを適用する本による1つの例を示します。 複合デザインパターン
最近、それを研究して試してみましたが、コンポジットについて心に留めておくべき強力な概念を認識しました。
コンポジットは、コレクションに含まれる複雑さを隠します。すなわち、それらをループし、それらをソートし、一部をフィルタリングするなど。単一の生物のように扱うことができます。
たとえば、ある犬小屋に犬がいて、別の犬小屋にたくさんの犬がいるとします。餌を与えてワクチンを接種したいが、1時間以内に食べた場合は餌を与えられず、最後の5時間以内にワクチンを接種した場合は餌を与えられず、嘔吐した場合はワクチンを接種できません。
さらに重要なことは、犬の品種Aが品種Bの前に食べるという包装順序の規則があります。ただし、品種Cの犬が周りにいて、彼の肺の頂上にbarえている場合を除きます。
これはすぐに、単に何も気にしたくないだけで、ヘルパーに電話して「すべての犬」に餌をやるように伝えます。さらに良いことに、3人のヘルパーが給餌、予防接種と嘔吐、barえ声と荷造り、その他すべての素晴らしいものを追跡します。
ヘルパーを呼び出すことにより、Compositionパターンに依存しました。 1匹でも10匹でも、犬小屋に行って、それぞれの犬小屋に「餌をやる」だけです。キャッシャーで手に余りにも多くを持っているので、犬でいっぱいの犬小屋がそれを自分自身で分類し、彼らがどのように食べているかを理解してほしい。
したがって、あなたにとって、犬はIDogであり、Feed()、Bark()、Vomit()、およびGetVaccine()です。犬小屋は犬でもあり、kennel.Feed()と呼びます。できました。犬小屋の犬小屋は、内部で今何をすべきかを把握する必要があります。それは、各犬の摂食および他の身体機能時間を追跡する時間管理メカニズムを備えている場合があります。それはすべてきちんとカプセル化されています。
binary trees
またはその他のcomplex data structures like list of lists of lists
-など...その後、すべての要素(クラス)が1つのインターフェイスを実装すると、1つのリーフまたはそれらのグループ全体で同じメソッドを実行できます-コピー、追加、削除、移動...正しく実装されました。とても便利でシンプルです。
答えは-
オブジェクトをツリー構造に構成して、全体の階層を表現します。複合により、クライアントは個々のオブジェクトとオブジェクトの構成を均一に処理できます。
フォーラムからコピー。
複合デザインパターンの実世界の例、内部に同じ親タイプまたはコンポーネントタイプのインスタンスを持つ可能性がある場合。
例:外国為替取引システムEx1
クロス通貨ペアを持っている可能性があります(AUD/EUR)= (AUD/USD and 1 /(EUR/USD))ここでポイントは、Instrument(Cross)can内部に2つのInstruments(Direct)があります。
別の例では
1つのInstrument(Cross)とInstrument(Direct)およびInstrument(Cross)は、さらに2つのInstrument(Direct)に分割できます。 SGD/CZK = USD/SGD(直接)およびUSD/CZK(クロス USD/SGD(直接)および(1/EUR/USD)(直接)およびEUR/CZK(直接))==
ここでのポイントは、すべての直接通貨ペアが見つかるまで分割を続けることです。
上記は、Composite Designパターンを使用して簡単に実装できます。
ネストされた類似オブジェクトを構築する場合は、複合デザインパターンを選択できます。たとえば、リアルタイムで、階層に基づいて会社員のツリー構造を表示する場合
これを願って 簡単な例 助けて
そして、よく知られている Composite UI Application Block は、Composite Patternに基づいています。