Decoratorパターン
Decoratorパターンは、既存のオブジェクトをラップするデザインパターンです。
自分なりにDecoratorパターンをクラス図にまとめてみました。
Decoratorパターンのクラス図
Decoratorパターンの解説
抽象クラスComponentを継承するComponent1があった場合に、Component1のoperationメソッドを少し変更した処理を行いたい場合、Component1を継承したサブクラスを作成する方法が考えられます。しかし、そういった少し変更したいものが多い場合、Component1を継承したサブクラスをどんどん多く定義していく必要があります。
そのサブクラスの処理を一旦Component型の属性をもつDecoratorクラスを作成し、そのDecoratorを継承するDecorator1,2クラスを作成することで、Decorator1,2で実装するoperationメソッド内で、componentのoperationメソッドを利用することで、componentのoperationの処理を任意に装飾(decoration)していくことができるようになるのです。
また、Decorator1,2各々のcomponent属性は、どちらもComponent型なので、Componentを継承しているDecorator1,2のどちらかがもう片方のオブジェクトをcomponent属性に含めることもできるわけです。
Decoratorパターンをどういう場合に使うか
例えばComponent1のoperationメソッドが、引数の文字を出力する処理だったとします。
その文字を
・「」で括る、
・太文字にする、
・アンダーラインを引く、
といった3つの装飾方法を組み合わせて行いたい場合、
・「」で括るようにoperationメソッドをオーバーライドしたクラス、
・太文字にするようにoperationメソッドをオーバーライドしたクラス、
・アンダーラインを引くようにoperationメソッドをオーバーライドしたクラス
・「」で括り、かつ太文字にするようにoperationメソッドをオーバーライドしたクラス
・「」で括り、かつアンダーラインを引くようにoperationメソッドをオーバーライドしたクラス
・「」で括り、かつ太文字にし、かつアンダーラインを引くようにoperationメソッドをオーバーライドしたクラス
の6つのサブクラスを作成することになります。
このような場合にDecoratorパターンを用いて、Componentオブジェクトを属性に持つDecoratorクラスを定義し、Decoratorを継承するDecorator1,2を作成してあげることで、Decorator1,2は、自分の属性のcomponentのoperationメソッドを呼び出せば、そのcomponentオブジェクトのoperationメソッドを呼び出すことができるようになるので、上記の例のような場合、
・Decoratorクラス
と、
・「」で括るようにoperationメソッドをオーバーライドしたクラス、
・太文字にするようにoperationメソッドをオーバーライドしたクラス、
・アンダーラインを引くようにoperationメソッドをオーバーライドしたクラス
の4つのサブクラスを作成すればよくなります。
作成するクラス数が減りますし、必要な場合に必要な装飾用のオブジェクトを動的に作成すればよくなります。
PlantUMLでDecoratorパターンのクラス図を記述する
Decoratorパターンのクラス図をPlantUMLで書いたときのソースです。
@startuml Decorator
abstract class Component{
+ abstract operation()
}
class Component1 extends Component{
+ operation()
}
abstract class Decorator extends Component{
- component: Component
--
+ operation() //componentのoperationを呼び出す
}
class Decorator1 extends Decorator{
+ operation() //componentのoperationを呼び出す+追加の処理
}
class Decorator2 extends Decorator{
+ operation() //componentのoperationを呼び出す+追加の処理
}
Decorator o--> Component
@enduml