コンテンツにスキップ

Decorator

オブジェクトを包むラッパーによって、ランタイムで機能を動的に追加するパターンです。

  • 武器への属性付与を組み合わせで適用したいとき
  • 既存コードを触らずに機能拡張したいとき
  • Component
  • Decorator Base
  • Concrete Decorator

以下のコードは、上で説明した状況を Unity プロジェクトの文脈で単純化した例です。

public interface IWeaponDamageCalculator
{
int CalculateDamage();
}
public sealed class BaseWeaponDamageCalculator : IWeaponDamageCalculator
{
public int CalculateDamage() => 10;
}
public abstract class WeaponDamageDecorator : IWeaponDamageCalculator
{
protected readonly IWeaponDamageCalculator innerCalculator;
protected WeaponDamageDecorator(IWeaponDamageCalculator innerCalculator)
{
this.innerCalculator = innerCalculator;
}
public abstract int CalculateDamage();
}
public sealed class FireDamageDecorator : WeaponDamageDecorator
{
public FireDamageDecorator(IWeaponDamageCalculator innerCalculator) : base(innerCalculator) { }
public override int CalculateDamage() => innerCalculator.CalculateDamage() + 5;
}
  • モジュール境界が明確になり、結合度を下げられます。
  • 既存コードを変更せずに機能拡張や統合がしやすくなります。
  • ラッパー層が深くなりすぎるとデバッグが難しくなります。
  • 責務境界が曖昧にならないよう、インターフェースは小さく保つべきです。

ラッパーを通して責務を動的に追加していくチェーンの流れです。

Decorator の流れ