← Назад к вопросам

Для чего нужен паттерн Декоратор?

2.3 Middle🔥 132 комментариев
#Паттерны проектирования

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основная цель паттерна Декоратор

Паттерн Декоратор (Decorator) относится к структурным паттернам проектирования и служит одной ключевой цели: динамическое добавление новой функциональности объекту без изменения его исходной структуры. В Unity-разработке он особенно ценен, так как позволяет гибко комбинировать поведение игровых объектов, компонентов или систем, избегая жесткой иерархии наследования и соблюдая принципы Открытости/Закрытости (Open/Closed Principle) и Единой ответственности (Single Responsibility Principle).

Проблемы, которые решает Декоратор

  1. "Взрывное" наследование. Представьте базовый класс Weapon. Если для создания комбинаций свойств (огненный, ледяной, ядовитый, зачарованный) использовать только наследование, вам потребуются классы FireWeapon, IceWeapon, PoisonWeapon, FireIceWeapon, FirePoisonWeapon и т.д. Количество классов растет экспоненциально.
  2. Жесткость и статичность. Наследование фиксирует поведение на этапе компиляции. Вы не можете "на лету" добавить эффект заморозки к уже существующему мечу в игровом процессе.
  3. Нарушение принципа единой ответственности. Класс оружия начинает отвечать и за нанесение урона, и за визуальные эффекты горения, и за логику отравления.

Как работает Декоратор: принцип "обертки"

Паттерн предполагает создание цепочки "оберток" вокруг основного объекта. Все эти обертки реализуют один и тот же интерфейс, что позволяет прозрачно заменять основной объект и последовательно накладывать на него декораторы.

Пример на C# для Unity:

// 1. Общий интерфейс для оружия и всех декораторов
public interface IWeapon
{
    float Damage { get; }
    string Description { get; }
    void Attack();
}

// 2. Конкретный класс оружия
public class Sword : IWeapon
{
    public float Damage =>乌 25f;
    public string Description => "Острый меч";

    public void Attack()
    {
        Debug.Log($"Нанесено {Damage} урона мечом.");
    }
}

// 3. Базовый абстрактный декоратор
public abstract class WeaponDecorator : IWeapon
{
    protected IWeapon _decoratedWeapon;

    public WeaponDecorator(IWeapon weapon)
    {
        _decoratedWeapon = weapon;
    }

    public virtual float Damage => _decoratedWeapon.Damage;
    public virtual string Description => _decoratedWeapon.Description;
    public virtual void Attack() => _decoratedWeapon.Attack();
}

// 4. Конкретные декораторы
public class FireEnchantment : WeaponDecorator
{
    private float _fireDamageBonus = 10f;

    public FireEnchantment(IWeapon weapon) : base(weapon) { }

    public override float Damage => base.Damage + _fireDamageBonus;
    public override string Description => base.Description + " с огненным зачарованием";

    public override void Attack()
    {
        base.Attack();
        Debug.Log("Цель подожжена!");
    }
}

public class FrostEnchantment : WeaponDecorator
{
    public FrostEnchantment(IWeapon weapon) : base(weapon) { }

    public override string Description => base.Description + " с ледяным зачарованием";

    public override void Attack()
    {
        base.Attack();
        Debug.Log("Цель замедлена!");
    }
}

// 5. Использование в коде
void Start()
{
    // Создаем базовое оружие
    IWeapon mySword = new Sword();

    // Динамически добавляем свойства
    mySword = new FireEnchantment(mySword);
    mySword = new FrostEnchantment(mySword);

    Debug.Log(mySword.Description); // "Острый меч с огненным зачарованием с ледяным зачарованием"
    mySword.Attack();
    // Вывод:
    // Нанесено 35 урона мечом.
    // Цель подожжена!
    // Цель замедлена!
}

Преимущества в контексте Unity-разработки

  • Гибкость и модульность: Можно легко добавлять новые типы улучшений (PoisonEnchantment, VampiricEnchantment), не трогая существующие классы.
  • Динамическая компоновка: Состав объекта определяется в рантайме, что идеально для систем крафта, прокачки или случайных модификаторов.
  • Чистота кода: Логика каждого эффекта изолирована в своем маленьком классе.
  • Применимость к компонентам: Паттерн можно адаптировать для расширения функциональности MonoBehaviour-компонентов (например, декораторы для поведения AI, визуальных эффектов рендерера).

Типичные сценарии использования в Unity

  1. Системы зачарования и улучшения оружия/брони (как в примере выше).
  2. Модификаторы игровых статусов (баффы/дебаффы). Декоратор может оборачивать объект PlayerStats, временно изменяя скорость, урон, защиту.
  3. Компоновка визуальных эффектов UI. Базовый элемент UI можно последовательно декорировать эффектами тени, свечения, анимации.
  4. Расширение поведения NPC. Базовый AIBehavior можно обернуть декораторами AggressiveDecorator, CautiousDecorator, комбинируя их.

Вывод

Паттерн Декоратор — это мощный инструмент для создания гибких, легко расширяемых систем, где требуется множественная, комбинируемая функциональность. Вместо создания монолитных классов или запутанных деревьев наследования он предлагает элегантное решение через композицию объектов в динамически формируемую цепочку, что делает код чище, а игровые механики — гораздо более вариативными.

Для чего нужен паттерн Декоратор? | PrepBro