Javaのデコレータパターン

1。概要

デコレータパターンを使用して、静的または動的にオブジェクトに追加の責任を付加できます。デコレータは、元のオブジェクトへの拡張インターフェイスを提供します。

このパターンの実装では、継承よりも構成を優先します。これにより、装飾要素ごとに何度もサブクラス化のオーバーヘッドを減らすことができます。このデザインに関連する再帰は、必要な回数だけオブジェクトを装飾するために使用できます。

2.デコレータパターンの例

クリスマスツリーオブジェクトがあり、それを装飾したいとします。装飾はオブジェクト自体を変更しません。クリスマスツリーに加えて、ガーランド、見掛け倒し、ツリートッパー、バブルライトなどの装飾アイテムを追加しているだけです。

このシナリオでは、元のGang ofFourの設計と命名規則に従います。まず、ChristmasTreeインターフェイスとその実装を作成します。

public interface ChristmasTree { String decorate(); }

このインターフェースの実装は次のようになります。

public class ChristmasTreeImpl implements ChristmasTree { @Override public String decorate() { return "Christmas tree"; } }

次に、このツリーの抽象TreeDecoratorクラスを作成します。このデコレータは、ChristmasTreeインターフェイスを実装するだけでなく、同じオブジェクトを保持します。同じインターフェイスから実装されたメソッドは、インターフェイスからdecorate()メソッドを呼び出すだけです。

public abstract class TreeDecorator implements ChristmasTree { private ChristmasTree tree; // standard constructors @Override public String decorate() { return tree.decorate(); } }

次に、装飾要素を作成します。これらのデコレータは、抽象TreeDecoratorクラスを拡張し、要件に応じてそのdecorate()メソッドを変更します。

public class BubbleLights extends TreeDecorator { public BubbleLights(ChristmasTree tree) { super(tree); } public String decorate() { return super.decorate() + decorateWithBubbleLights(); } private String decorateWithBubbleLights() { return " with Bubble Lights"; } }

この場合、次のことが当てはまります。

@Test public void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() { ChristmasTree tree1 = new Garland(new ChristmasTreeImpl()); assertEquals(tree1.decorate(), "Christmas tree with Garland"); ChristmasTree tree2 = new BubbleLights( new Garland(new Garland(new ChristmasTreeImpl()))); assertEquals(tree2.decorate(), "Christmas tree with Garland with Garland with Bubble Lights"); }

最初にすることを注意tree1というのオブジェクト、我々は1つのみで、それを飾るしているガーランド他の一方で、樹上村の我々は1で飾っているオブジェクトBubbleLightsと2つの花輪。このパターンにより、実行時に必要な数のデコレータを追加できる柔軟性が得られます。

4.結論

この記事では、デコレータのデザインパターンを見てみました。これは、次の場合に適しています。

  • オブジェクトの動作や状態を追加、拡張、さらには削除したい場合
  • クラスの単一のオブジェクトの機能を変更し、他のオブジェクトは変更しない場合

この例の完全なソースコードは、GitHubで入手できます。