
「構造パターン」の中でも実用頻度が非常に高い、Decorator(デコレーター)パターンをわかりやすく解説します。
このパターンは、既存のオブジェクトに新しい機能を“動的に”追加するためのパターンです。
コーヒーに「ミルク」「砂糖」「シナモン」を後から追加する感じでイメージしてみましょう。
よくある例
ログ出力に「タイムスタンプ」や「ファイル名」を追加する場合に使われます。
データ送信に「暗号化」「圧縮」処理を後付けする場合など。
ReactのHOC(高階コンポーネント)や、Pythonの@decoratorも概念的に同じ。
| 分野 |
Compositeの実例 |
| Web開発 |
Express.jsのmiddlewareチェーン |
| React |
HOC(Higher-Order Component)構造 |
| ログ処理 |
ロガーに「日付」「色」「保存先」を後付け |
| 通信 |
データ送信に暗号化や圧縮を追加 |
| ゲーム開発 |
キャラに「スピードアップ」「防御力アップ」を動的に付与 |
サンプルコード
例)メッセージを送信するクラスに、機能を「後付け」する。
基本クラス(Component)
class Notifier {
send(message) {
console.log(`通知: ${message}`);
}
}
デコレーターの基底クラス(Componentと同じインターフェース)
class NotifierDecorator {
constructor(notifier) {
this.notifier = notifier;
}
send(message) {
this.notifier.send(message);
}
}
追加機能①:Slack送信を追加
class SlackNotifier extends NotifierDecorator {
send(message) {
super.send(message);
console.log(`→ Slackに送信: ${message}`);
}
}
追加機能②:メール送信を追加
class EmailNotifier extends NotifierDecorator {
send(message) {
super.send(message);
console.log(`→ メールに送信: ${message}`);
}
}
実行例
let notifier = new Notifier();
notifier = new SlackNotifier(notifier);
notifier = new EmailNotifier(notifier);
notifier.send("デプロイが完了しました。");
出力結果
通知: デプロイが完了しました。
→ Slackに送信: デプロイが完了しました。
→ メールに送信: デプロイが完了しました。
ポイント解説
・Notifier(基本機能)に対して、SlackNotifierやEmailNotifierがラップして拡張している。
・クラスを継承せずに機能追加できるのが最大の特徴。
・どのデコレーターを重ねても、同じインターフェース(send())で呼べる。
メリット
・オブジェクト単位で柔軟に機能拡張できる。
・継承よりも組み合わせの自由度が高い。
・元クラスを一切変更せず、オープン・クローズド原則に適合。
デメリット
・デコレーターを多重に重ねると呼び出し順がわかりづらい。
・デバッグ時に「今どのデコレーターが作用しているか」を追うのが大変。
・過剰なラップ構造は複雑化の原因になる。
あとがき
Compositeとの違いは、以下のとおりです。
| 比較項目 |
Composite |
Decorator |
| 構造目的 |
階層構造を表現する(ツリー) |
機能を重ねて追加する(ラップ) |
| 主な関係 |
子を持つ親(再帰的) |
元オブジェクトを包む(入れ子) |
| 主な操作 |
再帰的な処理 |
チェーン的な処理 |
作られたインスタンスを、どんどんDecoratorしたインスタンスで上書きしていき、
最終実行する際に、一括処理できる点が少し複雑ですが、理解できると、複数処理をまとめる時に使えます。
Compositeしたリソースを、一括処理するようなイメージで使えそうですね。
複雑に感じる人は、自分でコードを書いて実装経験を積んで理解するのがいいですね。
0 件のコメント:
コメントを投稿