デコレータパターン


Decorator パターンを使用すると、構造を変更せずに既存のオブジェクトに新しい機能を追加できます。このタイプのデザイン パターンは構造パターンであり、既存のクラスのラッパーとして機能します。

このパターンは、元のクラスをラップする装飾クラスを作成し、クラス メソッド シグネチャの整合性を維持しながら追加機能を提供します。

次の例を通じて、デコレーター パターンの使用方法を示します。このうち、シェイプクラスを変更せずに、シェイプを別の色で装飾してみます。

はじめに

目的: 追加の責任をオブジェクトに動的に追加します。機能の追加という点では、デコレータ パターンはサブクラスを生成するよりも柔軟です。

主な解決策: 一般に、クラスを拡張するには継承を使用することがよくあります。継承によってクラスに静的な機能が導入され、拡張機能が増加するとサブクラスが拡張されます。

いつ使用するか: 多くのサブクラスを追加せずにクラスを拡張します。

解決方法: 特定の機能責任を分割し、デコレータ パターンを継承します。

キーコード: 1. Component クラスは抽象的な役割を果たすため、具体的に実装すべきではありません。 2. Component クラスを参照および継承するようにクラスを変更し、特にクラスを拡張して親クラスのメソッドをオーバーライドします。

応用例: 1. 孫悟空は「寺院」になったときも基本的には猿ですが、寺院の機能を持っています。 2. 絵画は額縁の有無に関係なく壁に掛けることができますが、通常は額縁があり、その額縁が実際に壁に掛けられます。壁に掛ける前に、絵画に釉薬をかけて額装することができ、絵画、ガラス、フレームが 1 つのオブジェクトを形成します。

利点: 装飾クラスと装飾クラスは独立して開発でき、相互に結合されません。装飾モードは、実装クラスの機能を動的に拡張できます。

短所: 多層装飾はより複雑です。

使用シナリオ: 1. クラスの機能を拡張します。 2. 機能を動的に追加し、動的にキャンセルします。

注: は継承の代わりに使用できます。

実装

ShapeインターフェースとShapeインターフェースを実装するエンティティクラスを作成します。次に、Shapeインターフェースを実装し、Shapeオブジェクトをインスタンス変数として使用する抽象装飾クラスShapeDecoratorを作成します。

RedShapeDecoratorは、ShapeDecoratorを実装するエンティティクラスです。

DecoratorPatternDemo、私たちのデモクラスはRedShapeDecoratorを使用してShapeオブジェクトを装飾します。

decorator_pattern_uml_diagram.jpgステップ 1

インターフェースを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ 2

インターフェースを実装するエンティティクラスを作成します。

Rectangle.java

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

Circle.java

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Circle");
   }
}

ステップ 3

Shape インターフェースを実装する抽象装飾クラスを作成します。

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;

   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }

   public void draw(){
      decoratedShape.draw();
   }	
}

ステップ 4

ShapeDecorator クラスを拡張するエンティティ装飾クラスを作成します。

RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);		
   }

   @Override
   public void draw() {
      decoratedShape.draw();	       
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

ステップ 5

RedShapeDecoratorを使用して、Shapeオブジェクトを装飾します。

DecoratorPatternDemo.java

public class DecoratorPatternDemo {
   public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}

ステップ 6

出力を確認します。

りー