##概要
既存のオブジェクトに新しい責任を動的に追加するパターン
以下の4種類のクラスからなる
- Componentクラス(責任を動的に追加できるオブジェクトのためのインターフェイスを定義)
- ConcreteComponentクラス(責任を動的に追加できる具体的なオブジェクトを定義)
- Decoratorクラス(オブジェクトへの参照を保持し、1.と一致したインターフェイスを定義)
- ConcreteDecoratorクラス(2.で定義されたオブジェクトに責任を追加するオブジェクトを定義)
##具体例と実装
コーヒーを例にすると
上記1~4はそれぞれ
- コーヒークラス(Coffeeクラス)
- アイスコーヒークラス(IcedCoffeeクラス)
- コーヒートッピングクラス(CoffeeToppingDecoratorクラス)
- 生クリームトッピングクラス、キャラメルトッピングクラス(CreamDecorator、CaramelDecoratorクラス)
が対応する。
コードの詳細は以下
coffeerb
class Coffee
def initialize(strength, volume)
@strength = strength
@volume = volume
end
def taste
end
def flavor
end
end
iced_coffee.rb
class IcedCoffee < Coffee
def initialize(strength, volume)
super
end
def taste
# スッキリした味わい
end
def flaver
# さっぱりしたフレーバー
end
end
coffee_topping_decorator.rb
class CoffeeToppingDecorator
def initialize(coffee)
@coffee = coffee
end
def taste
@coffee.taste
end
def flavor
@coffee.flavor
end
end
cream_decorator.rb
class CreamDecorator < CoffeeToppingDecorator
def taste
# @coffee.tasteにコクを追加
end
end
caramel_decorator.rb
class CaramelDecorator < CoffeeToppingDecorator
def flavor
# @coffee.flavorに甘い香りを追加
end
end
client.rb
caramel_cafe_au_lait = CaramelDecorator.new(CreamDecorator.new(IcedCoffee.new('濃い目', '普通サイズ')))
calamel_cafe_au_lait.taste # スッキリ、コクがある
calamel_cafe_au_lait.flavor # さっぱり、甘い香り
##メリット
- 責任の削除や追加が容易であるため、オブジェクトに複数の独立した責任を持たせたい場合に便利
- 動的に責任を追加できるため、責任ごとに多数の依存関係のあるクラスを作成しなくて良い
- 単純な部品を複数組み合わせてオブジェクトの機能を組み立てられるため、複雑なクラスを作成した場合に比べてアプリケーションが不要な機能を取り込む必要がなくなる上、予期せぬ機能追加にも対応しやすい
##まとめ
たくさんの機能を組み合わせたオブジェクトを作成する際に便利なパターン
動的な機能拡張や予期せぬ機能追加が予想される場合に用いる