Паттерны проектирования: Декоратор(Decorator)

Декоратор(Decorator) – структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Декоратор представляет гибкую альтернативу создания подклассов с целью расширения функционала.
Данный шаблон проектирования еще называют обёртка(Wrapper).
Задача: Есть объект, выполняющий свои основные функции, но может понадобиться добавить ему еще функциональности, которая будет выполняться до, после или вместо основного функционала.

Простейшая схема работы паттерна:
Перейдём к постановке проблемы, которую будет решать данный шаблон. Вы пишете программу для дилера автомобилей, при покупке автомобиля, покупатель может взять автомобиль в базовой комплектации, а может взять дополнительно кондиционер, покрышки и застраховать автомобиль.
Для начала создадим базовый класс автомобиля, класс будет абстрактный, будет содержать описание и цену автомобиля.
 
public abstract class AutoBase
    {

        protected String Description = "";

        public String GetDEscription()
        {
            return Description;
        }

        public abstract double GetCost();
    }
Теперь создадим классы для работы с автомобилями BMW и AUDI. Для простоты предположим, что цена на автомобили фиксированная(зададим её прямо в классе), при желании описание автомобиля и его цену можно задавать на этапе инициализации класса или позже, но в данном случае, для понимания работы шаблона этого не требуется.

Класс для автомобиля BMW:
 
    class BMW: AutoBase
    {

        public BMW()
        {
            Description = "BMW X5 — среднеразмерный кроссовер от немецкого автопроизводителя";
        }

        public override double GetCost()
        {
            return 25000;
        }
    }

Для автомобиля AUDI:
 
    class AUDI: AutoBase
    {

        public AUDI()
        {
            Description = "Audi A8 — автомобиль представительского класса, преемник модели Audi V8";
        }

        public override double GetCost()
        {
            return 31500;
        }
    }

Теперь создадим абстрактный класс для добавления комплектаций, назовём его Options, он будет наследоваться от класса AutoBase, дополнительные методы можно не объявлять. Сейчас реализуем класс для добавления в комплектацию страховки.
 
  class Insurance:Options
    {
        private readonly AutoBase _autoBase;

        public Insurance(AutoBase autoBase)
        {
            _autoBase = autoBase;
            if (autoBase != null)
            {
                Description = autoBase.GetDescription() + " + СТРАХОВКА на год";
            }
        }

        public override double GetCost()
        {
            double cost = 500;
            if (_autoBase != null)
            {
                cost += _autoBase.GetCost();
            }
            return cost;
        }
    }

Как можно заметить, класс страховки в конструктор принимает класс базового типа. Аналогично создаются классы для дополнительной покупки кондиционера и покрышек. Теперь осталось проверить работу программы, для этого я использовал следующий код:
 
    static void Main()
        {
            var auto1 = new BMW();
            var auto2 = new AUDI();

            PrintAuto(auto1);
            PrintAuto(auto2);
            Console.WriteLine("----------------------------------");

            var auto3 = new Insurance(new BMW());
            var auto4 = new Conditioner(new Tires(new AUDI()));
            var auto5 = new Tires(new Conditioner(new Insurance(new BMW())));
            PrintAuto(auto3);
            PrintAuto(auto4);
            PrintAuto(auto5);
        }

        public static void PrintAuto(AutoBase auto)
        {
            Console.WriteLine("{0} \nСтоимость: {1}$", auto.GetDescription(), auto.GetCost());
            Console.WriteLine("---");
        } 
 


Для реализации паттерна декоратор, был создан абстрактный класс AutoBase. В классах декораторах новые функции можно вызывать в требуемой последовательности – до, после или вместо основного функционала. Исходный код учебного проекта: http://1drv.ms/1z3fsP3

Добавить комментарий