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

Какие паттерны проектирования чаще всего используешь?

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

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

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

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

Паттерны проектирования в Unity-разработке

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

1. Singleton (Одиночка)

Использую осторожно, в основном для менеджеров, которые должны существовать в единственном экземпляре на протяжении всей сессии (например, AudioManager, GameManager). Важно избегать глобального состояния, где это возможно, поэтому предпочитаю зависимости через инъекцию или ScriptableObject для данных.

public class GameManager : MonoBehaviour
{
    private static GameManager _instance;
    public static GameManager Instance => _instance;

    private void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Destroy(gameObject);
            return;
        }
        _instance = this;
        DontDestroyOnLoad(gameObject);
    }

    public void LoadLevel(int levelIndex) { /* ... */ }
}

2. Observer (Наблюдатель)

Крайне полезен в играх для реализации реактивных систем. Вместо постоянных проверок в Update() использую события (C# events) или UnityEvent для уведомлений (например, о смерти персонажа, подборе предмета).

public class PlayerHealth : MonoBehaviour
{
    public event Action<int> OnHealthChanged;
    public event Action OnPlayerDied;

    private int _currentHealth = 100;

    public void TakeDamage(int damage)
    {
        _currentHealth -= damage;
        OnHealthChanged?.Invoke(_currentHealth);
        if (_currentHealth <= 0)
            OnPlayerDied?.Invoke();
    }
}

3. State (Состояние)

Идеален для управления сложным поведением: AI врагов, анимаций, режимов игры. Каждое состояние инкапсулирует свою логику, что упрощает добавление новых состояний и отладку.

public interface IEnemyState
{
    void Enter();
    void Update();
    void Exit();
}

public class PatrolState : IEnemyState
{
    public void Enter() { /* Начать патрулирование */ }
    public void Update() { /* Логика перемещения */ }
    public void Exit() { /* Очистка */ }
}

4. Object Pool (Пул объектов)

Критически важен для оптимизации в Unity, чтобы избежать частого создания/уничтожения объектов (пули, враги, эффекты). Создаю пул заранее и переиспользую объекты.

public class BulletPool : MonoBehaviour
{
    [SerializeField] private GameObject _bulletPrefab;
    private Queue<GameObject> _pool = new Queue<GameObject>();

    public GameObject GetBullet()
    {
        if (_pool.Count > 0)
            return _pool.Dequeue();
        return Instantiate(_bulletPrefab);
    }

    public void ReturnBullet(GameObject bullet)
    {
        bullet.SetActive(false);
        _pool.Enqueue(bullet);
    }
}

5. Command (Команда)

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

public interface ICommand
{
    void Execute();
    void Undo();
}

public class MoveCommand : ICommand
{
    private Transform _target;
    private Vector3 _previousPosition;

    public MoveCommand(Transform target, Vector3 newPosition)
    {
        _target = target;
        _previousPosition = target.position;
        Execute(newPosition);
    }

    public void Execute(Vector3 newPosition) => _target.position = newPosition;
    public void Undo() => _target.position = _previousPosition;
}

6. Component (Компонент)

Сам движок Unity построен на этом паттерне, и я следую принципу composition over inheritance. Создаю небольшие, переиспользуемые компоненты (например, HealthComponent, MovementComponent), которые добавляются к GameObject.

7. Service Locator / Dependency Injection (Локатор служб / Внедрение зависимостей)

Для управления зависимостями между системами использую упрощённый Service Locator или внедрение через конструктор/методы, особенно в тестируемом коде. Это уменьшает связность и упрощает модульное тестирование.

8. Model-View-Presenter (MVP) / Model-View-ViewModel (MVVM)

В UI-слое часто применяю MVP или MVVM (с помощью фреймворков типа UniRx), чтобы отделить логику от отображения. View отвечает за визуал, Model — за данные, Presenter/ViewModel — за связь между ними.

Критерии выбора паттернов

  • Производительность: Object Pool для оптимизации.
  • Гибкость: State и Component для легкого расширения.
  • Событийность: Observer для реактивности.
  • Тестируемость: Dependency Injection для изоляции логики.

Эти паттерны, в сочетании с архитектурными подходами (например, разделение на слои: Data, Logic, Presentation), позволяют мне строить проекты, которые легко поддерживать даже спустя годы после начала разработки. Ключ — понимать, когда паттерн уместен, а когда он добавляет избыточную сложность.

Какие паттерны проектирования чаще всего используешь? | PrepBro