Перейти к содержанию

Decorator.cs

Код подключён напрямую из исходного файла в кодировке UTF-8, поэтому эта страница всегда показывает его актуальную версию.

← К конспекту Скачать исходный файл

Decorator.cs
using System;

namespace DesignPatterns.Structural.Decorator
{
    // Общий интерфейс для базового объекта и всех декораторов
    public interface ICoffee
    {
        string Describe();
        decimal GetCost();
    }

    // Базовая реализация (то, что декорируем)
    public sealed class Espresso : ICoffee
    {
        public string Describe() => "Эспрессо";
        public decimal GetCost() => 90m;
    }

    // Базовый декоратор хранит ссылку на оборачиваемый объект
    // и по умолчанию просто делегирует ему вызовы.
    public abstract class CoffeeDecorator : ICoffee
    {
        protected readonly ICoffee Inner;

        protected CoffeeDecorator(ICoffee inner)
        {
            Inner = inner;
        }

        public virtual string Describe() => Inner.Describe();
        public virtual decimal GetCost() => Inner.GetCost();
    }

    public sealed class WithMilk : CoffeeDecorator
    {
        public WithMilk(ICoffee inner) : base(inner) { }

        public override string Describe() => $"{Inner.Describe()} + молоко";
        public override decimal GetCost() => Inner.GetCost() + 30m;
    }

    public sealed class WithSyrup : CoffeeDecorator
    {
        private readonly string _flavor;

        public WithSyrup(ICoffee inner, string flavor) : base(inner)
        {
            _flavor = flavor;
        }

        public override string Describe() => $"{Inner.Describe()} + сироп ({_flavor})";
        public override decimal GetCost() => Inner.GetCost() + 20m;
    }

    public static class Demo
    {
        public static void Run()
        {
            // Декораторы можно комбинировать в любом порядке и количестве -
            // каждый добавляет своё поведение поверх предыдущего, ничего не зная об остальных.
            ICoffee order = new WithSyrup(new WithMilk(new Espresso()), "карамель");

            Console.WriteLine($"{order.Describe()} - {order.GetCost():C}");
        }
    }
}