デコレーターデザインパターン

デコレーター設計パターンの実現テストします

シナリオ

コーヒーショップの例で勉強しましょう

珈琲店のレジアプリを作ろうと思います
コーヒーが数種類とトッピングが数種類あります
それぞれ価格があり、注文に従って合計金額を請求します

たとえば、注文としてダークローストコーヒーにモカを2倍入れてホイップを入れる場合、その合計が価格になります

商品価格
コーヒー
ダークロースト99円
カフェインレス110円
エスプレッソ200円
ハウスブレンドコーヒー100円
トッピング
モカ20円
豆乳15円
ホイップ10円

クラス図

コード

beverage1、beverage2、beverage3がそれぞれ注文とします

using P95Decorator.Coffee;
using P95Decorator.Condiment;

namespace P95Decorator
{
    class StarbuzzCoffee
    {
        public static void Main(string[] args)
        {
            Beverage beverage1 = new Espresso();
            Console.WriteLine($"{beverage1.Description} {beverage1.Cost}円");

            Beverage beverage2 = new DarkRoast();
            beverage2 = new Mocha(beverage2);
            beverage2 = new Mocha(beverage2);
            beverage2 = new Whip(beverage2);

            Console.WriteLine($"{beverage2.Description} {beverage2.Cost}円");

            Beverage beverage3 = new HouseBlend();
            beverage3 = new Soy(beverage3);
            beverage3 = new Mocha(beverage3);
            beverage3 = new Whip(beverage3);

            Console.WriteLine($"{beverage3.Description} {beverage3.Cost}円");
        }
    }
}
namespace P95Decorator
{
    public abstract class Beverage
    {
        public abstract string Description { get; set; }

        public abstract float Cost { get; }
    }
}
using System;
namespace P95Decorator
{
    public abstract class CondimentDecorator : Beverage
    {
        protected Beverage beverage;

        public override string Description { get; set; }
    }
}

Coffeeフォルダ

namespace P95Decorator.Coffee
{
    public class DarkRoast : Beverage
    {
        public DarkRoast()
        {
            Description = "ダークロースト";
        }

        public override float Cost => 99;

        public override string Description { get; set; }
    }
}
namespace P95Decorator.Coffee
{
    public class Decaf : Beverage
    {
        public Decaf()
        {
            Description = "カフェインレス";
        }

        public override float Cost => 110;

        public override string Description { get; set; }
    }
}
namespace P95Decorator.Coffee
{
    public class Espresso : Beverage
    {
        public Espresso()
        {
            Description = "エスプレッソ";
        }

        public override float Cost => 200;

        public override string Description { get; set; }
    }
}
namespace P95Decorator.Coffee
{
    public class HouseBlend : Beverage
    {
        public HouseBlend()
        {
            Description = "ハウスブレンドコーヒー";
        }

        public override float Cost => 100;

        public override string Description { get; set; }
    }
}

Condimentフォルダ

namespace P95Decorator.Condiment
{
    public class Mocha : CondimentDecorator
    {
        public Mocha(Beverage beverage)
        {
            this.beverage = beverage;
        }

        public override string Description => beverage.Description + "、モカ";

        public override float Cost => beverage.Cost + 20;
    }
}
namespace P95Decorator.Condiment
{
    public class Soy : CondimentDecorator
    {
        public Soy(Beverage beverage)
        {
            this.beverage = beverage;
        }

        public override string Description => beverage.Description + "、豆乳";

        public override float Cost => beverage.Cost + 15;
    }
}
namespace P95Decorator.Condiment
{
    public class Whip : CondimentDecorator
    {
        public Whip(Beverage beverage)
        {
            this.beverage = beverage;
        }

        public override string Description => beverage.Description + "、ホイップ";

        public override float Cost => beverage.Cost + 10;
    }
}

結果

エスプレッソ 200円
ダークロースト、モカ、モカ、ホイップ 149円
ハウスブレンドコーヒー、豆乳、モカ、ホイップ 145円

参考