見出し画像

🛠Decoratorパターンは服を着せていくイメージ Decoratorパターンとストラテジとの違いはガッツ(肝)とスキン(皮膚)の違い 再帰的なパターン結合

オブジェクト指向プログラミングにおいて、デコレーター・パターンは、同じクラスの他のインスタンスの振る舞いに影響を与えることなく、個々のオブジェクトに動的に振る舞いを追加できるようにするデザイン・パターンである

https://en.wikipedia.org/wiki/Decorator_pattern

デコレーター・パターンを使うと、あるオブジェクトの機能を静的に、あるいは場合によっては実行時に、同じクラスの他のインスタンスとは独立して拡張(装飾)することができる。これは、元のクラスをラップする新しいDecoratorクラスを設計することで実現できます。このラッピングは、次のような一連の手順で実現できます:
1.元のComponentクラスをDecoratorクラスにサブクラス化する(UMLダイアグラムを参照);
2.Decorator クラスに、フィールドとして Component ポインターを追加します;
3.Decoratorクラスで、DecoratorコンストラクタにComponentを渡してComponentポインタを初期化する;
4.Decoratorクラスで、すべてのComponentメソッドをComponentポインタに転送する。
5.ConcreteDecoratorクラスで、動作を変更する必要があるComponentメソッドをオーバーライドする。
このパターンは、複数のデコレーターを重ねることで、オーバーライドされたメソッドに新しい機能を追加できるように設計されています。

Javaと.NET FrameworkのI/O Streams実装は、デコレーター・パターンを取り入れている。

Adapterはインターフェースの互換性を、Decoratorは動的な責務追加を、Strategyはアルゴリズムの柔軟な切り替えをそれぞれサポートします。

これは分かりやすい


これならわかる、サンプルもぜひ見よう

function run() {
   var user = new User("Kelly");
   user.say();
   var decorated = new DecoratedUser(user, "Broadway", "New York");
   decorated.say();
   log.show();
}

ソースを見るだけで何をしているものかはわかりやすい。デコレーターという名前も被せてる感じが非常に分かりやすい。

時には、クラス全体ではなく、個々のオブジェクトに責任を追加したいこともあります。例えば、グラフィカル・ユーザー・インターフェース・ツールキットでは、境界線のようなプロパティやスクロールのような動作をユーザー・インターフェース・コンポーネントに追加することができます。

GoFでのデコレーターの役割はデコレートするレイヤーのような機能に注目する。まるで「どてら」のように重ね着をしてデコレーションするわけだが、透明なプレートとしてイメージしているようだ。GUIだけでなく、ストリームの例も説明している。Javaのことしか知らないが、なんたらバッファードはデコレータの好例ということになる。

こっちのほうかな

次の奥義はストラテジになるが、以下の文章が不気味に響き渡る。

A decorator lets you change the skin of an object; a strategy lets you change the guts. These are two alternative ways of changing an object.デコレーターはオブジェクトの表層を変える、ストラテジは内臓をかえる。

ガッツ(臓物)を変えたけりゃ、ストラテジを使えとなる

Decorator パターンは、既存のオブジェクトに動的に新しい責任や機能を追加するためのデザインパターンです。このパターンは、サブクラス化を使用することなく、オブジェクトの機能を拡張するために使用されます。Decorator パターンの鍵となる点は、同じ基本インターフェースまたは抽象クラスを継承または実装することによって、オブジェクトをラップする「デコレータ」として動作するクラスを定義することです。
再帰的な結合とは、Decorator パターンの特徴的な構造であり、デコレータが別のデコレータや基本のコンポーネントをラップできることを意味します。これにより、複数のデコレータを連鎖的に組み合わせることで、動的にオブジェクトの振る舞いや責任をカスタマイズすることができます。

例:

考えてみてください:あるビデオストリーミングサービスにて、基本的なビデオ再生機能があります。これが基本的なコンポーネントです。
しかし、以下のような追加機能を持つデコレータがあります:

  1. AdDecorator: ビデオの前に広告を追加します。

  2. SubtitleDecorator: ビデオに字幕を追加します。

  3. WatermarkDecorator: ビデオに透かしを追加します。

これらのデコレータを使用して、基本のビデオ再生機能に上記の追加機能を動的に組み込むことができます。さらに、これらのデコレータを再帰的に組み合わせることで、複数の機能を組み合わせたビデオ再生体験を作成することができます。
例えば、広告付きで字幕が表示されるビデオを作成する場合、AdDecorator でビデオをラップし、次にその結果を SubtitleDecorator でラップします。このように、再帰的な結合を使用して、必要な機能の組み合わせを簡単に構築することができます。
このアプローチのメリットは、異なる機能の組み合わせを柔軟に作成できること、また新しい機能を追加する際に既存のコードを変更することなくデコレータとして追加できることです。


Dot

digraph DecoratorPattern {
    node [shape=record]

    Component [label="{Component|+operation(): void}"]
    ConcreteComponent [label="{ConcreteComponent|+operation(): void}"]
    Decorator [label="{Decorator|+operation(): void\n+addedBehavior(): void}"]
    ConcreteDecoratorA [label="{ConcreteDecoratorA|+operation(): void\n+addedBehavior(): void}"]
    ConcreteDecoratorB [label="{ConcreteDecoratorB|+operation(): void\n+addedBehavior(): void}"]

    Component -> ConcreteComponent [arrowhead="none"]
    Component -> Decorator [arrowhead="none"]
    Decorator -> ConcreteDecoratorA [arrowhead="none"]
    Decorator -> ConcreteDecoratorB [arrowhead="none"]
    Decorator -> Component [label="decorates" dir="back"]

    {rank=same; ConcreteDecoratorA ConcreteDecoratorB}
}


お願い致します