コンセプト
デコレーター パターンは、オブジェクトに責任を動的に割り当てます。機能を拡張するために、デコレータは継承に代わるより柔軟な手段を提供します。
デコレーターと装飾されたオブジェクトは同じスーパータイプを持ちます。
オブジェクトを 1 つ以上のデコレータでラップできます。
デコレーターと装飾されたオブジェクトは同じスーパータイプを持つため、元のオブジェクト (ラップされた) が必要なときはいつでも、代わりに装飾されたオブジェクトを使用できます。
デコレーターは、特定の目的を達成するために、委任されたデコレーターの動作の前または後に独自の動作を追加できます。
オブジェクトはいつでも装飾できるため、実行時にお気に入りのデコレータを使用して
オブジェクトを動的かつ無制限に装飾できます。
Java では、io パッケージの下にある多くのクラスは、次のような典型的なデコレータ パターンを具体化したものです:
new BufferedOutputStream(OutputStream out)
new BufferedInputStream(InputStream in);
new PrintWriter(OutputStream out)
new FilterReader(Reader in);
装飾されたクラスは、装飾されたクラスと同じインターフェイスを実装します。
装飾されたクラスは、どの実装クラスが装飾するかを気にしません。
同じビジネスメソッドであるため、装飾されたクラスは、装飾されたクラスのメソッドを呼び出して拡張します。装飾クラスの機能
インスタンス:
クラス図
public interface IReader { void read(); } public class Reader implements IReader { @Override public void read() { System.out.println("read of Reader"); } } public class BufferedReader implements IReader { private IReader mReader; public BufferedReader(IReader reader) { this.mReader = reader; } @Override public void read() { System.out.println("read of BufferedReader"); mReader.read(); } } public class Test { public static void main(String[] args) { Reader reader = new Reader(); reader.read(); System.out.println("----------"); BufferedReader bufferedReader = new BufferedReader(reader); bufferedReader.read(); } }
特徴:
1. 装飾されたオブジェクトと実際のオブジェクトは同じインターフェイスを持ちます。このようにして、クライアント オブジェクトは、実際のオブジェクトと同じ方法で装飾されたオブジェクトと対話できます。
2. 装飾されたオブジェクトには、実際のオブジェクトへの参照が含まれています。
3. 装飾されたオブジェクトは、クライアントからのすべてのリクエストを受け入れます。これらのリクエストを実際のオブジェクトに転送します。
4. 装飾オブジェクトは、これらのリクエストを転送する前または後に、いくつかの追加機能を追加できます。これにより、特定のオブジェクトの構造を変更することなく、実行時に追加の機能を外部から追加できるようになります。
オブジェクト指向設計では、通常、特定のクラスの機能拡張は継承によって実現されます。装飾後、実物を保持して機能性を高めます。
デコレーター パターンとアダプター パターンの違い:
新しい責任について: アダプターは変換中に新しい責任を追加することもできますが、主な目的はここではありません。デコレータ パターンは主に、デコレータに新しい責任を追加します。
ラップするオブジェクトについて: アダプターは、適応される人の詳細 (つまり、適応クラス) を知っています。デコレータはそのインターフェイスが何であるかのみを知り、その特定の型 (基底クラスであるか別の派生クラスであるか) は実行時にのみわかります。