【C++】Decorator(別名:Filter、デザインパターン)

## Decoratorとは?
**オブジェクトに動的に新しい機能を追加する**ことを目的とした設計。
- 実行時にDecoratorを組み合わせて機能を拡張できるため、**柔軟性を向上させる**
- 各Decoratorを一つの機能に特化させることで、
**コードの可読性と保守性を向上させられる**
- 複数のDecoratorを組み合わせることで、**複雑な機能を実現することができる**

### C++
```C++:Decorator.cpp
#include <iostream>
#include <string>

/// <summary>
/// ソフトクリームの抽象クラス
/// </summary>
class Softcream
{
public:
	inline virtual std::string Output(void) const = 0;
};

/// <summary>
/// バニラソフトクリーム
/// </summary>
class VanillaSoftcream
	: public Softcream
{
public:
	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "バニラソフト";
	}
};

/// <summary>
/// 抹茶ソフトクリーム
/// </summary>
class MatchaSoftcream
	: public Softcream
{
public:
	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "抹茶ソフト";
	}
};

/// <summary>
/// チョコソフトクリーム
/// </summary>
class ChocoSoftcream
	: public Softcream
{
public:
	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "チョコソフト";
	}
};

/// <summary>
/// デコレーター
/// </summary>
class Decorator
	: public Softcream
{
public:
	/// <summary>
	/// コンストラクタ
	/// </summary>
	Decorator(Softcream* _softcream)
	{
		softcream = _softcream;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	virtual ~Decorator()
	{
		delete softcream;
	}

	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return softcream->Output();
	}

	// アップキャストして実体化可能なオブジェクトを格納するポインタ
	Softcream* softcream;
};

/// <summary>
/// トッピング(チョコレート)
/// </summary>
class ChocolateTopping
	: public Decorator
{
public:
	/// <summary>
	/// コンストラクタ
	/// </summary>
	ChocolateTopping(Softcream* _softcream)
		: Decorator(_softcream)
	{}

	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "チョコトッピングの" + softcream->Output();
	}
};

/// <summary>
/// トッピング(ストロベリー)
/// </summary>
class StrawberryTopping
	: public Decorator
{
public:
	/// <summary>
	/// コンストラクタ
	/// </summary>
	StrawberryTopping(Softcream* _softcream)
		: Decorator(_softcream)
	{}

	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "ストロベリートッピングの" + softcream->Output();
	}
};

/// <summary>
/// トッピング(アーモンド)
/// </summary>
class AlmondTopping
	: public Decorator
{
public:
	/// <summary>
	/// コンストラクタ
	/// </summary>
	AlmondTopping(Softcream* _softcream)
		: Decorator(_softcream)
	{}

	/// <summary>
	/// 出力
	/// </summary>
	/// <returns>出力結果</returns>
	inline std::string Output(void) const override
	{
		return "アーモンドトッピングの" + softcream->Output();
	}
};

int main(void)
{
	// ソフトクリーム
	Softcream* softcream = new VanillaSoftcream;
	std::cout << softcream->Output() << std::endl;

	// トッピング付き
	Decorator* decorator =
		new AlmondTopping
		(new ChocolateTopping
		(new StrawberryTopping
		(new MatchaSoftcream)));
	std::cout << decorator->Output() << std::endl;

	delete decorator;
	delete softcream;

	return 0;
}
```

### C#
```C#:Decorator.cs
using System;

/// <summary>
/// ソフトクリームの抽象クラス
/// </summary>
public interface Softcream
{
    string Output();
}

/// <summary>
/// バニラソフトクリーム
/// </summary>
public class VanillaSoftcream : Softcream
{
    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public virtual string Output()
    {
        return "バニラソフト";
    }
}

/// <summary>
/// 抹茶ソフトクリーム
/// </summary>
public class MatchaSoftcream : Softcream
{
    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public virtual string Output()
    {
        return "抹茶ソフト";
    }
}

/// <summary>
/// チョコソフトクリーム
/// </summary>
public class ChocoSoftcream : Softcream
{
    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public virtual string Output()
    {
        return "チョコソフト";
    }
}

/// <summary>
/// デコレーター
/// </summary>
public abstract class Decorator : Softcream
{
    public Softcream softcream;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public Decorator(Softcream _softcream)
    {
        softcream = _softcream;
    }

    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public virtual string Output()
    {
        return softcream.Output();
    }
}

/// <summary>
/// トッピング(チョコレート)
/// </summary>
public class ChocolateTopping : Decorator
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public ChocolateTopping(Softcream _softcream) : base(_softcream) { }

    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public override string Output()
    {
        return "チョコトッピングの" + softcream.Output();
    }
}

/// <summary>
/// トッピング(ストロベリー)
/// </summary>
public class StrawberryTopping : Decorator
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public StrawberryTopping(Softcream _softcream) : base(_softcream) { }

    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public override string Output()
    {
        return "ストロベリートッピングの" + softcream.Output();
    }
}

/// <summary>
/// トッピング(アーモンド)
/// </summary>
public class AlmondTopping : Decorator
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public AlmondTopping(Softcream _softcream) : base(_softcream) { }

    /// <summary>
    /// 出力
    /// </summary>
    /// <returns>出力結果</returns>
    public override string Output()
    {
        return "アーモンドトッピングの" + softcream.Output();
    }
}

class Program
{
    static void Main()
    {
        // ソフトクリーム
        Softcream softcream = new VanillaSoftcream();
        Console.WriteLine(softcream.Output());

        // トッピング付き
        Softcream decorator =
            new AlmondTopping
            (new ChocolateTopping
            (new StrawberryTopping
            (new MatchaSoftcream())));
        Console.WriteLine(decorator.Output());
    }
}
```