Featured image of post Decoratorパターン調査ドキュメント

Decoratorパターン調査ドキュメント

Decoratorパターンに関する包括的な調査結果 - GoF定義、SOLID原則との関係、実装例を網羅

Decoratorパターン調査ドキュメント

調査目的

Decoratorパターン(デコレーターパターン)に関する包括的な調査を行い、シリーズ記事作成の基盤となる情報を収集する。

  • 調査対象: GoF定義、構造、利用シーン、メリット/デメリット、SOLID原則との関係、Perl/Moo実装
  • 想定読者: Perl/Mooでデザインパターンを学習したいエンジニア
  • 調査実施日: 2026年01月17日

1. 概要

1.1 GoFによる定義と意図(Intent)

要点:

  • 定義: オブジェクトに動的に追加の責任(responsibilities)を付加する。Decoratorは、サブクラス化よりも柔軟な機能拡張の代替手段を提供する
  • 意図: オブジェクトを変更せずに、実行時に動的かつ透過的に責任を追加する
  • 分類: 構造パターン(Structural Pattern)
  • 別名: Wrapper(ラッパー)

根拠:

  • Gang of Four(GoF)の『Design Patterns: Elements of Reusable Object-Oriented Software』における正式定義
  • 開放閉鎖原則(OCP)をサポート: クラスは拡張に対して開いているが、変更に対して閉じている
  • 他のオブジェクトに影響を与えずに、個々のオブジェクトに対して責任を追加できる

出典:

信頼度: 10/10(GoF公式定義に基づく複数の権威ある情報源からの一致した記述)


1.2 パターンの構造(Structure)

要点:

Decoratorパターンは4つの主要コンポーネントで構成される:

コンポーネント役割説明
Component共通インターフェース動的に装飾可能なオブジェクトのインターフェース定義
ConcreteComponent具象コンポーネントComponentインターフェースを実装する基本オブジェクト。追加責任を付加される対象
Decorator抽象デコレータComponentインターフェースを実装し、Componentへの参照を保持。操作をComponentに委譲
ConcreteDecorator具象デコレータDecoratorを拡張し、委譲の前後に追加の振る舞いを実装。状態やメソッドの追加も可能

構造図(テキスト表現):

1
2
3
4
5
6
7
Component
   |
   +-- ConcreteComponent
   |
   +-- Decorator (抽象クラス、Componentへの参照を保持)
         |
         +-- ConcreteDecorator (追加機能を実装)

根拠:

  • GoF書籍のクラス図とパターン説明に基づく
  • Component、ConcreteComponent、Decorator、ConcreteDecoratorはGoF標準の参加者(Participants)
  • Decoratorは委譲(delegation)とコンポジション(composition)を利用する

出典:

信頼度: 10/10(複数の信頼できる技術文献における一貫した構造定義)


2. 用途

2.1 具体的な利用シーン

要点:

利用シーン説明具体例
Java I/O ストリーム最も有名な実装例。基本的なストリームに対して、バッファリング、データ型解析、圧縮などを動的に追加BufferedInputStream, DataInputStream, GZIPOutputStream
WebフレームワークミドルウェアHTTPリクエスト/レスポンス処理チェーンにおいて、認証、ロギング、検証などを層状に追加Servlet Filter (Java EE), Springミドルウェア
ロギング既存オブジェクトの操作にログ記録機能を動的に追加LoggingNotifier でコアの Notifier をラップ
認証/認可セキュリティチェックを既存サービスに動的に追加AuthenticationDecorator で認証チェックを挿入
キャッシングデータサービス呼び出しにキャッシュ層を動的に追加CachingDecorator でキャッシュ確認→本処理の流れを実装
React HOCReact Higher-Order Componentsは、コンポーネントを受け取り拡張されたコンポーネントを返す関数形式のDecoratorwithAuth, withData, withLoader など
GUIウィジェットウィンドウやボタンにスクロールバー、枠、影などを動的に追加ScrollDecorator, BorderDecorator

根拠:

  • Java I/Oは教科書的なDecorator実装として広く知られ、InputStream/OutputStreamがComponent、各種ストリームがConcreteDecoratorの役割
  • Webフレームワークにおけるミドルウェアパターンは、リクエスト処理パイプラインに動的に機能を追加するDecoratorの応用
  • React HOCは関数型プログラミングのhigher-order function概念とDecoratorパターンの融合

出典:

信頼度: 9/10(実装例が多数確認できる実績あるユースケース。ただし、フレームワークによって実装詳細は異なる)


3. サンプルコード

3.1 Perl/Mooでの基本実装例

要点:

Perl/Mooでは、hasでコンポーネント参照を保持し、around修飾子で既存メソッドをラップする手法が有効。 Moo::Roleを用いたRole合成により、複数のDecorator機能を動的に組み込むことも可能。

基本的なDecorator実装(Moo + around修飾子):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 言語: perl
# バージョン: 5.36以上
# 依存: Moo(cpanm Mooでインストール)

# Component(インターフェース)
package Component;
use v5.36;
use Moo::Role;

requires 'operation';

1;

# ConcreteComponent(具象コンポーネント)
package ConcreteComponent;
use v5.36;
use Moo;

with 'Component';

sub operation ($self) {
    return "Base operation";
}

1;

# Decorator(基底デコレータ)
package Decorator;
use v5.36;
use Moo;

with 'Component';

has component => (
    is       => 'ro',
    does     => 'Component',
    required => 1,
);

sub operation ($self) {
    return $self->component->operation;
}

1;

# ConcreteDecoratorA(具象デコレータ)
package ConcreteDecoratorA;
use v5.36;
use Moo;

extends 'Decorator';

sub operation ($self) {
    my $base = $self->component->operation;
    return "[DecoratorA: $base]";
}

1;

# ConcreteDecoratorB(具象デコレータ)
package ConcreteDecoratorB;
use v5.36;
use Moo;

extends 'Decorator';

sub operation ($self) {
    my $base = $self->component->operation;
    return "[DecoratorB: $base]";
}

1;

# 使用例
use ConcreteComponent;
use ConcreteDecoratorA;
use ConcreteDecoratorB;

my $component = ConcreteComponent->new;
my $decorated = ConcreteDecoratorA->new(component => $component);
my $double_decorated = ConcreteDecoratorB->new(component => $decorated);

say $double_decorated->operation;
# 出力: [DecoratorB: [DecoratorA: Base operation]]

Roleベースのアプローチ(around修飾子使用):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 言語: perl
# バージョン: 5.36以上
# 依存: Moo(cpanm Mooでインストール)

# 基本クラス
package Printer;
use v5.36;
use Moo;

sub print_message ($self, $msg) {
    say "Message: $msg";
}

1;

# ログ機能を追加するRole(Decorator的役割)
package Role::Logger;
use v5.36;
use Moo::Role;

around print_message => sub ($orig, $self, @args) {
    say "[LOG] Calling print_message with: @args";
    $self->$orig(@args);   # 元のメソッド呼び出し
    say "[LOG] Finished print_message";
};

1;

# Roleを組み込んだクラス
package LoggingPrinter;
use v5.36;
use Moo;

extends 'Printer';
with 'Role::Logger';

1;

# 使用例
use LoggingPrinter;

my $printer = LoggingPrinter->new;
$printer->print_message('Hello, Decorator!');
# 出力:
# [LOG] Calling print_message with: Hello, Decorator!
# Message: Hello, Decorator!
# [LOG] Finished print_message

根拠:

  • Mooのhas属性でComponentへの参照を保持し、委譲パターンを実現
  • around修飾子は既存メソッドの前後に処理を挿入する機能で、Decorator的な動作を簡潔に実装可能
  • Moo::Roleを用いることで、複数のDecorator機能をRoleとして定義し、動的に合成できる
  • CPANにはMooseX::Traits(実行時Role合成)などDecoratorパターンを支援するモジュールも存在

出典:

信頼度: 9/10(Moo公式ドキュメントと実装例に基づく。ただし、動的なDecorator追加には追加の工夫が必要な場合がある)


3.2 CPAN上の関連モジュール

要点:

モジュール名概要Decorator関連用途
MooseポストモダンなPerlオブジェクトシステムhandlesオプションで委譲、MooseX拡張で高度なDecorator実装
MooMoose互換の軽量OOシステムhandlesで委譲、around修飾子で簡易Decorator
MooseX::Traits実行時Role合成実行時にRoleを動的に適用してDecoratorパターンを実現
MooseX::Role::Parameterizedパラメータ化可能なRole柔軟なDecoratorをRoleとして定義
Role::Tiny軽量Role実装Moo/Mooseと互換性のあるRole合成

根拠:

  • MooseとMooはPerlの主流OOシステムで、GoF Decoratorパターンの実装に必要な委譲、合成、Roleをサポート
  • handlesオプションを使うことで、Componentへのメソッド委譲を宣言的に記述可能
  • MooseX名前空間には多数の拡張モジュールが存在し、Decorator実装を支援

出典:

信頼度: 8/10(CPANの検索結果と各モジュールドキュメントに基づく。ただし、Decorator専用モジュールではないため、実装は開発者次第)


4. 利点・欠点

4.1 メリット

要点:

メリット説明具体例
動的な機能追加実行時にオブジェクトに機能を追加・削除可能ログ、認証、キャッシュを必要に応じて動的に追加
継承よりも柔軟サブクラス爆発を回避。必要な機能の組み合わせを実行時に構成MilkDecorator、SugarDecoratorを任意に組み合わせ
単一責任原則(SRP)遵守各Decoratorが単一の責任に集中。機能が分離され、保守性向上LoggingDecorator、AuthDecorator、CachingDecoratorが独立
開放閉鎖原則(OCP)遵守既存コードを変更せずに新機能を追加可能新しいDecoratorを追加しても、ComponentやConcreteComponentは不変
再利用性とモジュール性同じDecoratorを複数の異なるComponentに適用可能LoggingDecoratorを複数のサービスで再利用

根拠:

  • Decoratorパターンはコンポジションを用いるため、継承の制約(静的、組み合わせ爆発)を回避
  • SOLID原則のうち、特にOCP(拡張に開き、変更に閉じる)とSRP(単一責任)を強く支援
  • 各Decoratorは明確に責任が分離され、テストや保守が容易

出典:

信頼度: 10/10(広く認知されたDecoratorパターンの利点であり、複数の権威ある情報源で一致)


4.2 デメリット

要点:

デメリット説明影響対策
多数の小クラス生成各機能ごとにDecoratorクラスが必要。クラス数が増大コードベースが肥大化、ナビゲーション困難命名規則統一、ドキュメント整備
デバッグの複雑化複数Decoratorの層により、実行時の挙動追跡が困難スタックトレース複雑化、バグ発見困難ログ機能強化、デバッグツール活用
順序依存性Decoratorの適用順序により結果が変わる順序を誤ると意図しない動作適用順序を明確に文書化、単体テスト実施
抽象化オーバーヘッド各Decorator層が抽象化レベルを追加。場合により性能影響多層Decoratorで実行時オーバーヘッドDecorator数を最小限に、パフォーマンステスト
型チェック問題ラップにより元のオブジェクト型が隠蔽されるinstanceof等での型判定が困難インターフェース統一、型情報の明示
小規模・静的組み合わせには不適組み合わせが固定・少数の場合、継承の方がシンプル不要な複雑性導入要件に応じてパターン選択

根拠:

  • Decoratorパターンは柔軟性と引き換えに、間接層の増加とクラス数増大を伴う
  • 複数Decoratorの積み重ねにより、どのDecoratorがどの機能を追加したか追跡が困難になる
  • 順序依存性は特にミドルウェアパターンで顕著(認証→ロギング vs ロギング→認証で結果が異なる)

出典:

信頼度: 9/10(複数の信頼できる技術文献で指摘されているデメリット。実装・運用経験からの知見)


5. SOLID原則との関係

5.1 開放閉鎖原則(Open/Closed Principle: OCP)との関係

要点:

  • OCP定義: ソフトウェアエンティティ(クラス、モジュール、関数等)は、拡張に対して開いているが、変更に対して閉じているべき
  • Decoratorとの関係: DecoratorパターンはOCPの教科書的実装例
  • 既存のConcreteComponentを一切変更せずに、新しいDecoratorクラスを追加することで機能拡張を実現
  • 新機能は新しいDecoratorとして「拡張」され、既存コードは「変更」されない

具体例:

Coffeeクラスに対して、ミルク、砂糖、ホイップクリームなどのオプションを追加する場合:

  • 継承アプローチ: CoffeeWithMilk, CoffeeWithSugar, CoffeeWithMilkAndSugar, …とサブクラスが爆発
  • Decoratorアプローチ: MilkDecorator, SugarDecorator, WhipDecoratorを定義し、任意に組み合わせ。Coffeeクラスは不変

根拠:

  • OCP違反の典型例は、新機能のたびに既存クラスを修正すること
  • Decoratorは新しい責任を追加する際に、既存コードを変更せず新しいクラスを作成するだけで対応
  • GoF書籍でもDecoratorパターンがOCPをサポートすることが明示されている

出典:

信頼度: 10/10(SOLID原則とDecorator関係は広く認知された理論的基盤)


5.2 単一責任原則(Single Responsibility Principle: SRP)との関係

要点:

  • SRP定義: クラスは変更する理由を1つだけ持つべき(単一の責任のみを持つ)
  • Decoratorとの関係: 各Decoratorは単一の追加責任のみを持つ
  • 機能をDecoratorに分離することで、ConcreteComponentは本来の責任に集中
  • ロギング、認証、キャッシュなどの横断的関心事を個別のDecoratorクラスに分離

具体例:

Notifierクラスがメッセージ送信を担当する場合:

  • SRP違反例: Notifierクラス内にログ記録、認証チェック、送信履歴保存などを全て実装
  • Decorator適用: LoggingDecorator, AuthDecorator, HistoryDecoratorとして分離。Notifierは送信のみに責任を持つ

根拠:

  • 複数の責任を1つのクラスに詰め込むと、変更理由が複数となり、保守性・テスト容易性が低下
  • Decoratorパターンは責任を明確に分離するため、SRP遵守に貢献
  • 各Decoratorは独立してテスト可能で、再利用性が高い

出典:

信頼度: 10/10(SRPとDecoratorの関係は明確で、複数の教育的リソースで説明されている)


6. 関連トピックとの比較

6.1 Pythonデコレータとの違い

要点:

項目Pythonデコレータ(言語機能)GoF Decoratorパターン
対象関数・メソッドオブジェクト・クラスのインスタンス
適用時期定義時(関数ロード時)実行時(インスタンス生成時)
単位関数単位(@decorator構文)オブジェクト単位(クラスラッピング)
主な用途ロギング、タイミング、アクセス制御GUIウィジェット拡張、I/Oストリーム
パラダイム関数型プログラミングオブジェクト指向プログラミング

根拠:

  • Pythonの@decoratorは、関数を受け取り関数を返す高階関数(higher-order function)であり、定義時に適用される
  • GoF Decoratorは、オブジェクトを受け取りラップした新しいオブジェクトを返すパターンで、実行時に適用される
  • 名前の類似性により混同されやすいが、概念的には異なる
  • Pythonデコレータでもクラスベースデコレータを用いてGoF Decoratorパターンを実装することは可能

出典:

信頼度: 9/10(Pythonコミュニティと設計パターンコミュニティで広く議論されている区別)


6.2 React Higher-Order Components (HOC)との関係

要点:

  • React HOCは、コンポーネント(関数またはクラス)を受け取り、拡張されたコンポーネントを返す関数
  • HOCはDecoratorパターンの関数型プログラミング版と見なせる
  • 元のコンポーネントを変更せずに、新しい機能(認証、データフェッチ、ローディング表示など)を追加
  • 高階関数(higher-order function)の概念に基づき、Decoratorパターンの意図を関数型で実現

具体例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const withAuth = (WrappedComponent) => {
  return function EnhancedComponent(props) {
    if (!isAuthenticated()) {
      return <Redirect to="/login" />;
    }
    return <WrappedComponent {...props} />;
  };
};

const ProtectedPage = withAuth(MyPage);

根拠:

  • HOCは元のコンポーネントをラップし、追加の振る舞いを注入する点でDecoratorパターンと一致
  • Reactコミュニティでは、HOCをDecoratorパターンの実装として説明する文献が多い
  • ただし、現在ではReact Hooksが主流となり、HOCの使用頻度は減少傾向

出典:

信頼度: 9/10(Reactコミュニティでの共通理解。ただし、Hooks導入以降の位置づけは変化している)


7. 関連記事・内部リンク

7.1 関連する既存記事

記事タイトルリンク関連性
第6回-これがPrototypeパターンだ! - mass-producing-monsters/2026/01/17/004437/Prototypeパターンも動的オブジェクト生成に関するパターン。Decoratorとは異なるが、同じくGoF構造パターン
【目次】PerlとMooでモンスター軍団を量産してみよう(全6回)/2026/01/17/004454/Perl/Mooでのデザインパターン実装シリーズ。Decoratorと同様の技術スタック
これがFactory Methodパターンだ!/2026/01/17/132354/Factory Methodも生成に関するパターン。Decoratorは構造パターンで補完関係
【目次】PerlとMooでAPIレスポンスシミュレーターを作ってみよう(全8回)/2026/01/17/132411/Perl/MooでのOOP実践シリーズ。Decoratorパターンの実装基盤
第8回-売り切れ状態を追加しよう(OCP実践) - Mooを使って自動販売機シミュレーターを作ってみよう/2026/01/10/001244/開放閉鎖原則(OCP)の実践例。DecoratorもOCPを強く支援
第10回-これがStateパターンだ! - Mooを使って自動販売機シミュレーターを作ってみよう/2026/01/10/001650/Stateパターンも振る舞いパターン。Decoratorとは異なるが、同じくGoF
【目次】Mooを使って自動販売機シミュレーターを作ってみよう(全10回)/2026/01/10/001853/Perl/MooでのStateパターン実装シリーズ
第10回-これがObserverパターンだ! - Perlでハニーポット侵入レーダーを作ろう/2026/01/18/061448/Observerパターンも振る舞いパターン。Decoratorと組み合わせ可能

調査方法:

  • /home/runner/work/www.nqou.net/www.nqou.net/content/post 配下を grep で検索
  • 検索キーワード: デザインパターン, design.pattern, Decorator, Moo, SOLID, OOP, 開放閉鎖

信頼度: 10/10(サイト内記事の直接確認)


調査まとめ

主要な発見

  1. GoF定義の明確性: Decoratorパターンは、動的な責任追加を目的とした構造パターンであり、継承に代わる柔軟な拡張手段として確立されている

  2. SOLID原則との強い親和性: 特に開放閉鎖原則(OCP)と単一責任原則(SRP)の実践において、Decoratorパターンは理想的な実装モデルを提供する

  3. 実世界での豊富な実装例: Java I/Oストリーム、Webミドルウェア、React HOCなど、多様な分野でDecoratorパターンが実装されており、実用性が高い

  4. Perl/Mooでの実装可能性: Mooのhasaround修飾子、Moo::Roleを活用することで、PerlでもDecoratorパターンを簡潔に実装可能。CPANにはMooseX::Traitsなど支援モジュールも存在

  5. デメリットへの認識: 多数の小クラス生成、デバッグ複雑化、順序依存性など、Decoratorパターンには明確なトレードオフが存在。適用場面の見極めが重要

  6. 用語の混同に注意: Pythonデコレータ、React HOC、GoF Decoratorパターンは関連するが異なる概念。文脈に応じた正確な理解が必要

  7. 既存記事との連携: サイト内には既にPrototype、Factory Method、State、Observerなど複数のGoFパターン実装記事が存在。Decoratorパターンを加えることで、デザインパターンのカバレッジが向上


作成日: 2026年01月17日
担当エージェント: investigative-research
保存先: content/warehouse/decorator-pattern.md


チェックリスト

  • 各セクションに「要点」「根拠」「出典」「信頼度」が記載されているか
  • 出典URLが有効であるか
  • 信頼度の根拠が明確か(1-10の10段階評価)
  • 仮定がある場合は明記されているか
  • 内部リンク候補が調査されているか(grep で content/post を検索)
  • タグが英語小文字・ハイフン形式か
  • 提案・次のステップ・記事構成案・テーマ提案が含まれていないか(調査ドキュメントは事実情報のみを記録)
comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。