28

Decorator パターンと Delegation パターン (存在する場合) の違いは何ですか? 実装の詳細だけでなく、ユースケースの違いや主観的な使い方についても知りたいです。

EDIT :これらのパターン (Java IO クラスで装飾が使用されるため、特に委譲) が使用されているソースコード (OS プロジェクト内) を指すことができますか? ダミーの例だけでなく、実際の使用法を探しています。たぶん、これらのパターンは同じで、タイトルが異なるだけです。この意見を自由に書いてください。

4

2 に答える 2

32

Decorator は Delegation を使用しますが、非常に特殊な方法で使用します。

委任 (または構成) は、他のいくつかのオブジェクトの使用を調整することによって複雑な動作を構築する一般的な方法ほどパターンではありません。多くの場合、セットまたは静的な方法で使用されます。「設定または静的」とは、次のような意味です。

class Delegator {
  private final ClassA a = new ClassA();
  private final ClassB b = new ClassB();

  public void doWork() {
     a.setup();
     final ResFromA resa = a.getRes();
     b.setup();
     b.consume(resa);
  }

}

Delegator は、ClassA または ClassB とタイプまたはインターフェースを共有せず、a と b の両方の正確なタイプを認識していることに注意してください。

デコレーターは、委任を使用して実行時に論理エンティティに動作を追加する動的な方法です。Decorator では、すべてのエンティティが共通のインターフェースを共有し、委任を使用してそれらの作業を連結します。

public interface Item {
  public void drawAt(final int x, final int y);
}

public class CircleAround implements Item {
  private final Item wrapped;
  private final int radius;

  public CircleAround(public final Item wrapped, public final int radius) {
    this.wrapped = wrapped;
    this.radius = radius;
  }

  public void drawAt(final int x, final int y) {
    // First handle whatever we are wrapping
    wrapped.drawAt(x,y);
    // Then add our circle
    Graphics.drawCircle(x, y, radius);
  }

}

最初の例とは異なり、CircleAround はラップするアイテムの正確なタイプを認識せず、共通のインターフェイスを共有することに注意してください。

于 2012-11-15T08:17:11.020 に答える
9

「委任パターン」は、パターンであるかどうかのリトマス試験紙にかなり明確に失敗すると思います。たとえば、人々は今でも「工場のパターンを知っている」といつも言っています。Factoryパターンはありません。これはイディオムです (ジェームズ・コプリエンによる高度な C++ を参照)。そのページもかなり弱いです。私は単純な委任を責任の逆転とは考えていません。

デコレータは、装飾されるコードを拡張する必要がある場合に使用されます。デコレーターは、デコ対象をラップし、そのメソッドを呼び出します。前または後に処理を行います。これは、アスペクトが登場するときに人々がデコレーターについてかなり多く話しているのを目にする理由の 1 つです。それは、そのコホートとの協力ではなく、仲介に依存するパターンです。(これが、ソースがない場合など、多くの場合、Decorator を使用しなければならない理由でもあります。)

デコレータは、機能しているものを取り出して別のことをさせたいが、インターフェイスをまったく変更したくない場合に最適です。CRUD メソッドを含むインターフェースを出力する Repository クラスがあるとします。次に、キャッシュを追加します。リポジトリをデコレートする CachedRepository を作成し、読み取り時にキャッシュを調べます。そこにない場合は、通常のリポジトリ メソッドを呼び出します。それ以外の場合は、キャッシュされたコピーを返すだけです。Repository クラスのコードは変更されておらず、クラスのユーザーはキャッシュについて何も知りません。

于 2012-11-15T00:20:04.250 に答える