概要
デコレーターパターンは、既存のオブジェクトに新しい機能を追加するためのデザインパターンである。基本的な考え方は、元のオブジェクトをラップし、動的に機能を拡張する点にある。これにより、サブクラス化せずに機能を追加でき、柔軟で保守性の高い設計が可能となる。
利用目的
デコレーターパターンは、クラスの機能を動的に拡張する際に使用される。特に、複数の異なる拡張が必要な場合や、継承による設計が複雑になりすぎる場合に有効である。例えば、IO 処理において、バッファリングや圧縮、暗号化などの機能を重ねて適用する際に役立つ。
注意点
デコレーターパターンを過度に使用すると、オブジェクトが多層化してコードが複雑になり、可読性が低下する可能性がある。また、デコレータの連鎖が深くなると、デバッグやメンテナンスが難しくなる場合があるため、適切な設計が求められる。
実装
Component
// 機能追加したいコンポーネントのインターフェース
public interface Component {
void operation();
}
ConcreteComponent
// 機能追加したいコンポーネントの実装
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("基本機能");
}
}
Decorator
// デコレータの抽象クラス
// 【注意!】機能追加したいコンポーネントのインターフェースをimplementsしている!
public abstract class Decorator implements Component {
// 【注意!】機能追加したいコンポーネントを所有する!
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
ConcreteDecoratorA
// 追加機能Aを持つ具体的なデコレータ
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
// 【注意!】ここで機能追加!
@Override
public void operation() {
super.operation();
System.out.println("追加機能A");
}
}
ConcreteDecoratorB
// 追加機能Bを持つ具体的なデコレータ
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
// 【注意!】ここで機能追加!
@Override
public void operation() {
super.operation();
System.out.println("追加機能B");
}
}
App
// Mainクラス
public class App {
public static void main(String[] args) {
Component component = new ConcreteComponent();
Component decoratedComponentA = new ConcreteDecoratorA(component);
// 【注意】ConcreteDecoratorAもComponentをimplementsしているので、ConcreteDecoratorBに渡せる!
Component decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);
// 基本機能 + 追加機能A + 追加機能B を実行
decoratedComponentB.operation();
}
}