Javaのデコレータパターン

Javaのデコレータパターン

1. 概要

A Decorator pattern can be used to attach additional responsibilities to an object either statically or dynamically.デコレータは、元のオブジェクトへの拡張インターフェイスを提供します。

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

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

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

image

For this scenario, we’ll follow the original Gang of Four design and naming conventions.最初に、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つのGarlandのみで装飾しているのに対し、他のtree2オブジェクトは1つのBubbleLightsと2つの%で装飾していることに注意してください。 (t4)s。 このパターンにより、実行時に必要な数のデコレータを追加できる柔軟性が得られます。

4. 結論

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

  • オブジェクトの動作や状態を追加、強化、または削除する場合

  • クラスの単一オブジェクトの機能を変更し、他のオブジェクトを変更しない場合

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