複合パターンとデコレータパターンの違いは何ですか?
7 に答える
彼らは通常、手をつないで行きます。その点で、複合パターンを使用すると、デコレータパターンも使用されることがよくあります。
複合パターンを使用すると、外部コードで構造全体を単一のエンティティとして表示できるように、階層構造(要素のツリーなど)を構築できます。したがって、リーフエンティティへのインターフェイスは、複合エンティティのエンティティとまったく同じです。したがって、本質的には、複合構造内のすべての要素は、一部がリーフノードであり、その他が構造全体であっても、同じインターフェイスを持っているということです。多くの場合、ユーザーインターフェイスはこのアプローチを使用して、簡単に構成できるようにします。
http://en.wikipedia.org/wiki/Composite_pattern
デコレータパターンを使用すると、エンティティに別のエンティティを完全に含めることができるため、デコレータを使用すると、含まれているエンティティと同じように見えます。これにより、デコレータは、エンティティの外観を変更することなく、カプセル化するものの動作やコンテンツを変更できます。たとえば、デコレータを使用して、含まれている要素の動作を変更せずに、含まれている要素の使用に関するログ出力を追加できます。
複合パターンとデコレータの構造は同じように見えますが、意図が異なります。
Compositeは、リーフとコンポジットへの統一されたインターフェイスを提供します。
デコレータデコレータは、統一されたインターフェイスを提供しながら、リーフに追加機能を提供します。
例
複合パターン:従来のWindowsフォルダーとファイル。Windowsフォルダは複合です。ファイルは葉です。それらのいずれかをダブルクリックすると、ファイル/フォルダが開きます-ダブルクリックは統一されたインターフェイスです。
デコレータパターン:バッファリングされたio-java.io.FileWriter
およびjava.io.BufferedWriter
両方が拡張されjava.io.Writer
ます。java.io.BufferedWriter
複合であり、FileWriter
葉です。BufferedWriter
にバッファリングの追加の責任(または機能)を追加しFileWriter
ます。
write()
メソッドは統合インターフェースですが、バッファリングは追加機能です。
デコレータは、コンポーネントが1つしかない縮退したコンポジットと見なすことができます。ただし、デコレータは追加の責任を追加します。これは、オブジェクトの集約を目的としたものではありません。
これは、4人のギャングによる「デザインパターン-再利用可能なオブジェクト指向ソフトウェアの要素」で述べられていることです。
違いは、おそらく実装よりも目的の1つです。場合によっては、サブクラス化よりも複合パターンの方が望ましいことがあります。たとえば、他のクラスのインスタンスをクラスに追加し、転送インターフェイスを介して機能を公開することで、クラスに必要な機能を追加できます。
デコレータを使用すると、クラスのインスタンスのクライアントがデコレータがあることを知る必要がなくても、機能(通常は単一の機能)をクラスに透過的に追加できます。たとえば、Djangoのビューの「login_required」デコレータは例外を発生させます。ユーザーがログインしていない場合、それ以外の場合、ビューはデコレータがない場合と同じように動作します。
どちらの場合も、あるオブジェクトが別のオブジェクトに埋め込まれていますが、達成しようとしていることはほぼ間違いなく異なります。
構造の違い
これは、PlantUMLを使用して再現されたGoFブックのクラス図です。
意図の違い
デコレータの目的は、単一のコンポーネントを装飾することです(UMLダイアグラムは、装飾されたコンポーネントの多重度を実際に示す必要があります)が、コンポジットの目的は、コンポーネント全体をコンポジットにグループ化することです(ここでも、UMLは1つ以上のコンポーネントを含むコンポジット)。
Operation()
Decoratorは、ConcreteDecoratorsを介して動作(メソッドの動作を強化する)を追加することを目的としていますが、Compositeはコンポーネントを収集することを目的としています。
デコレータパターンを使用して、特定のオブジェクトの機能を静的に拡張(装飾)することができます。同じクラスの他のインスタンスとは関係なく、実行時に拡張(装飾)することもできます。
構成が原因で可能です。デコレータにはコンポーネントが含まれていると同時に、コンポーネントインターフェイスが実装されています。
複合パターンは、オブジェクトのグループがオブジェクトの単一のインスタンスと同じように扱われることを示しています。コンポジットの目的は、オブジェクトをツリー構造に「コンポジット」して、部分全体の階層を表すことです。
複合パターンを実装すると、クライアントは個々のオブジェクトと構成を均一に扱うことができます。
構造は同じように見えますが、意図と使用例は異なります。
デコレータパターンのユースケース:
- オブジェクトの責任と動作は動的に追加/削除する必要があります
- 具体的な実装は、責任と行動から切り離す必要があります
- サブクラス化はコストがかかりすぎて、責任を動的に追加/削除できません
これら2つのパターンの主な違い:
- デコレータは、サブクラス化せずにオブジェクトに責任を追加できるように設計されています。コンポジットの焦点は装飾ではなく表現にあります
- デコレータは、追加の責任を追加/削除します。これは、オブジェクトの集約を目的としたものではありません。
理解を深めるためのSEの便利な投稿:
複合:
- 再帰を使用したツリー構造です。
- LeafとCompositeのインターフェースは同じです
- オブジェクト間の統一
デコレータ:
- 別のエンティティが含まれています。
- 複合オブジェクトを変更せずに、新しい機能を複合オブジェクトに追加します。