Decorator パターン
Decoratorパターンは、GoF(Gang of Four)によって定義されたデザインパターンの一つで、既存のオブジェクトに新しい機能や振る舞いを動的に追加するためのものです。このパターンは、オブジェクトを装飾するように機能を追加することから、デコレータ(Decorator)という名前が付けられています。
Decoratorパターンの基本構造
Decoratorパターンは、以下の主要な要素で構成されます。
Component (コンポーネント): 機能を追加されるオブジェクトのインターフェースを定義します。通常は抽象クラスまたはインターフェースで表現されます。
ConcreteComponent (具象コンポーネント): Componentインターフェースを実装した具体的なオブジェクトです。Decoratorによって機能が追加される対象となります。
Decorator (デコレータ): Componentインターフェースを実装し、ConcreteComponentをラップする抽象クラスです。Component型の参照を持ち、追加機能の実装を委譲します。
ConcreteDecorator (具象デコレータ): Decoratorクラスを継承し、具体的な機能を追加するクラスです。必要に応じて複数のConcreteDecoratorを組み合わせて、様々な機能を追加できます。
Decoratorパターンの仕組み
Decoratorパターンは、既存のオブジェクトを新しいDecoratorオブジェクトでラップすることで機能を追加します。Decoratorのコンストラクタでラップ対象のComponentオブジェクトを受け取り、そのオブジェクトをメンバ変数として保持します。そして、DecoratorはComponentインターフェースを実装することで、ラップされたオブジェクトと同じインターフェースを提供します。このため、クライアントはDecoratorオブジェクトをComponentオブジェクトと同じように扱うことができ、実行時に動的に機能を追加できます。
Decoratorパターンと継承
Decoratorパターンは、既存のクラスを拡張する際に、クラスの継承の代替手段としてよく用いられます。継承はコンパイル時に機能を拡張するのに対し、Decoratorパターンはプログラムの実行時に動的に機能を追加します。これにより、柔軟な機能拡張と、クラスの肥大化を防ぐことができます。
利用例: 価格計算システム
価格計算システムを例に、Decoratorパターンの利用例を説明します。
`Price` (Component): 価格計算のインターフェースを定義します。
`PrimePrice` (ConcreteComponent): 基本価格を計算するクラス。
`MarginPrice` (Decorator): 価格にマージンを加算するデコレータ。
`WholesalePrice` (ConcreteDecorator): 卸売価格を計算するデコレータ。
`DoublePrice` (ConcreteDecorator): 価格を2倍にするデコレータ。
この例では、基本価格(`PrimePrice`)に対して、マージン(`MarginPrice`)、卸売価格(`WholesalePrice`)、2倍(`DoublePrice`)などの機能を追加するために、Decoratorパターンを利用できます。例えば、`WholesalePrice`と`DoublePrice`を組み合わせて、卸売価格を2倍にするような機能も動的に作成できます。
Decoratorパターンの利点
柔軟性: 実行時に動的に機能を追加できるため、柔軟な設計が可能です。
拡張性: 新しい機能を追加する際に、既存のクラスを修正する必要がありません。
組み合わせ: 複数のデコレータを組み合わせることで、様々な機能を作成できます。
クラスの肥大化防止: 継承によるクラスの肥大化を防ぎ、よりシンプルで理解しやすいコードを維持できます。
Decoratorパターンの欠点
複雑性: デコレータを多用すると、クラス構造が複雑になる可能性があります。
デバッグ: デコレータが連鎖すると、デバッグが難しくなる場合があります。
関連するデザインパターン
Adapterパターン: インターフェースの異なるクラスを協調させるためのパターン。
Abstract Factoryパターン: 関連するオブジェクト群を生成するためのパターン。
Compositeパターン: 木構造のオブジェクトを表現するためのパターン。
その他関連用語
* イミュータブル: 変更不可能なオブジェクト。Decoratorパターンでラップされたオブジェクトの変更を防ぐために利用されることがあります。
Decoratorパターンは、オブジェクトの機能を拡張するための強力なツールであり、適切な場面で活用することで、柔軟で拡張性の高いシステムを構築できます。