→ Пошук по сайту       Увійти / Зареєструватися
Знання Патерни Структурні патерни — Structural patterns

9. Декоратор — Decorator

9.	Декоратор — Decorator

Розкажу я вам про лікаря, який мав хорошу й швидку машину Mercedes. Оскільки він лікар львівської лікарні, то по дорозі на роботу він часто попадає у корки, тому він спізнюється і це його виводить із себе, в результаті чого страждають... Хто? Його пацієнти. В нашого лікаря є мрія, в якій його машина перетвориться на карету швидкої допомоги і всі інші автомобілі уступатимуть йому дорогу на роботу. Тільки одна проблема із цим: швидка вміє сигналити сиреною, а його мерс не має такої можливості. Нам, як програмістам, було б добре декорувати (decorate) «мерс», таким чином, щоб він почав голосно «вити». Як ми це можемо зробити?

Декоратор використовується для надання деякої додаткової функціональності нашим об'єктам.

В нашому прикладі, ми хочемо додати функціональність сирени до конкретної імплементації автомобіля. Нам нічого не заважатиме причепити на машину і газовий розпилювач абощо. Отже, маємо базовий клас автомобіля (Car):

Уривок коду 9.1. Базовий клас Автомобіля

 class  Car
{
    protected String BrandName { get; set; }
    public virtual void Go()
    {
        Console.WriteLine("I'm " + BrandName + " and I'm on my way...");
    }
}
// Конкретна реалізація класу Car
class  Mercedes : Car
{
    public Mercedes()
    {
        BrandName = "Mercedes";
    }
}

Для того щоб зберегти контракт базового класу Car і мати базовий клас для всіх інших «прибамбасних» функціональностей, створимо CarDecorator, що так само наслідується від Car. Цей клас і буде основою для патерну Декоратор: 

Уривок коду 9.2. Декоратор

 class  DecoratorCar : Car
{
    protected Car DecoratedCar { get; set; }
    public DecoratorCar(Car decoratedCar)
    {
        DecoratedCar = decoratedCar;
    }
    public override void Go()
    {
        DecoratedCar.Go();
    }
}

Як ми уже зауважили, цей клас агрегує справжній автомобіль, або іншими словами обгортає DecoratedCar. Через це даний патерн ще називають Обгорткою (або Wrapper). Можливо ви десь зустрічали цю ж назву і для дизайн патерну Адаптер. Його так само могли називати «враппер». Обидва патерни можуть так називати, але слід розрізняти їхнє призначення. Патерн Адаптер застосовується для представлення одного під виглядом іншого, а Декоратор для додавання до існуючого більше функціональності, хоч вони обоє агрегують певний об’єкт.

Настав час для «прибамбасів». Ми додаємо додаткову функціональність до будь-якої машини (чи то «мерс» чи то «беха»), наслідуючися від CarDecorator класу. Тут ми додали простий екстеншин біпкання.

Уривок коду 9.3. «Декор» карети швидкої допомоги

 class  AmbulanceCar : DecoratorCar
{
    public AmbulanceCar(Car decoratedCar)
        : base(decoratedCar)
    {
    }
    public override void Go()
    {
        base.Go();
        Console.WriteLine("... beep-beep-beeeeeep ...");
    }
}

І власне те, чого ми добивалися
Викорисання вигладає дуже мило — ми покриваємо мерседес «фічами» швидкої і отримуємо мрію лікаря (змінна doctorsDream). Опісля ми можемо покрити цей об’єкт ще якимись штукенціями і, що важливо, ми це все можемо робити динамічно. Сниться лікарю біпкалка — передаємо його мерс у Декоратор AmbulanceCar, а сниться йому кулемет на даху автомобіля — передаємо у декоратор ArmorCar. 

Уривок коду 9.4. Використання патерну

 var doctorsDream = new AmbulanceCar(new Mercedes());
doctorsDream.Go();

Вивід:

 I'm Mercedes and I'm on my way...
... beep-beep-beeeeeep ...

Надіюся що цей вивід був очікуваний. А тепер швидко глянемо на UML цієї мудрості-чудасії:

UML-діаграма 6. Декоратор

Цей патерн має щось спільне і з Компонувальником і Адаптером. Адаптер може змінити інтерфейс поведінки, а Декоратор ні (ми наслідуємося від Car). Компонувальник працює із великою кількістю компонент, а не як Декоратор – тільки із однією.
 

По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Робота представлена за умовами ліцензії Creative Commons Attribution-NonCommercial 3.0 Unported License.

загрузка...
Сторінки, близькі за змістом