Decoratorパターン

Head First デザインパターンのメモ。

Decoratorパターン

オブジェクトに付加的な責務を動的に付与する。
デコレータはサブクラスの代替となる柔軟な機能拡張手段を提供する。

特徴

  • 装飾するオブジェクトと同じスーパークラスを持つ
  • 複数のDecoratorクラスを使用してオブジェクトをラップできる
  • 装飾するオブジェクトのメソッド呼び出し前後で機能を追加することで振舞いを変更する
  • 一般的にコンポーネントのクライアントに対して透過的
  • 多数の小さなオブジェクトができる可能性があり乱用すると複雑になる可能性がある

実装

コーヒーショップの注文システムを設計する場合。

public abstract class Beverage {
    String description = "不明な飲み物";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

// トッピング用の抽象クラス
// Beverageクラスと交換可能にするため、Beverageを拡張する
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}


// 飲み物の実装
public class Expresso extends Beverage {
    public Expresso() {
        description = "エスプレッソ";
    }

    public double cost() {
        return 1.99;
    }
}

// トッピングの実装
public class Mocha extends CondimentDecorator {
    Beverage beverage;

    public Mocha(Beverage beverage) {
        // ラップする飲み物を保持するインスタンス変数
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + "、モカ";
    }

    public double cost() {
        return .20 + beverage.cost();
    }
}

設計原則

クラスは拡張に対しては開かれた状態であるべきであるが、
変更に対しては閉じた状態であるべきである。

継承をしないで再利用を実現する

サブクラス化で振舞いを継承すると、その振舞いは静的に設定される。
さらにすべてのサブクラスが同じ振舞いを継承しなければならない。
コンポジションを使って振舞いを拡張すると、実行時に振舞いを決定できる。
動的にオブジェクトを構成することで、変更ではなく新しいコードの記述で機能を追加できる。


Observerパターン