Примеры кода

Принцип единственной ответственности (SRP)

Каждый класс должен иметь только одну причину для изменения.

// Плохо: Класс с несколькими обязанностями
public class UserManager
{
    public void AddUser(User user) { /* ... */ }
    public void SendEmail(User user, string message) { /* ... */ }
    public void LogError(string error) { /* ... */ }
}

// Хорошо: Разделение на отдельные классы
public class UserManager
{
    public void AddUser(User user) { /* ... */ }
}

public class EmailService
{
    public void SendEmail(User user, string message) { /* ... */ }
}

public class Logger
{
    public void LogError(string error) { /* ... */ }
}

Singleton (Одиночка)

Гарантирует, что у класса есть только один экземпляр.

public class GameManager
{
    private static GameManager _instance;
    
    // Приватный конструктор
    private GameManager() { }
    
    // Потокобезопасная реализация
    private static readonly object _lock = new object();
    
    public static GameManager Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new GameManager();
                    }
                }
            }
            return _instance;
        }
    }
    
    // Методы класса
    public void StartGame() { /* ... */ }
    public void EndGame() { /* ... */ }
}

Adapter (Адаптер)

Позволяет объектам с несовместимыми интерфейсами работать вместе.

// Целевой интерфейс, который ожидает клиент
public interface IEnemy
{
    void Attack();
    void Move();
}

// Адаптируемый класс
public class OldEnemy
{
    public void OldAttack() { /* ... */ }
    public void OldMove() { /* ... */ }
}

// Адаптер
public class EnemyAdapter : IEnemy
{
    private readonly OldEnemy _oldEnemy;
    
    public EnemyAdapter(OldEnemy oldEnemy)
    {
        _oldEnemy = oldEnemy;
    }
    
    public void Attack()
    {
        _oldEnemy.OldAttack();
    }
    
    public void Move()
    {
        _oldEnemy.OldMove();
    }
}

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

Определяет зависимость «один ко многим» между объектами.

// Интерфейс наблюдателя
public interface IObserver
{
    void Update(string message);
}

// Интерфейс субъекта
public interface ISubject
{
    void RegisterObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
    void NotifyObservers();
}

// Конкретный субъект
public class GameEventSystem : ISubject
{
    private readonly List _observers = new List();
    private string _gameState;
    
    public void RegisterObserver(IObserver observer)
    {
        _observers.Add(observer);
    }
    
    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }
    
    public void NotifyObservers()
    {
        foreach (var observer in _observers)
        {
            observer.Update(_gameState);
        }
    }
    
    public void SetGameState(string state)
    {
        _gameState = state;
        NotifyObservers();
    }
}

// Конкретный наблюдатель
public class UIManager : IObserver
{
    public void Update(string message)
    {
        Debug.Log($"UI обновлен: {message}");
        // Обновление пользовательского интерфейса
    }
}

MVC (Model-View-Controller)

Разделение приложения на три основных компонента.

// Модель
public class PlayerModel
{
    public int Health { get; private set; } = 100;
    public int Score { get; private set; }
    
    public event Action OnHealthChanged;
    public event Action OnScoreChanged;
    
    public void TakeDamage(int damage)
    {
        Health = Math.Max(0, Health - damage);
        OnHealthChanged?.Invoke();
    }
    
    public void AddScore(int points)
    {
        Score += points;
        OnScoreChanged?.Invoke();
    }
}

// Представление
public class PlayerView : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI healthText;
    [SerializeField] private TextMeshProUGUI scoreText;
    
    public void UpdateHealth(int health)
    {
        healthText.text = $"Здоровье: {health}";
    }
    
    public void UpdateScore(int score)
    {
        scoreText.text = $"Очки: {score}";
    }
}

// Контроллер
public class PlayerController : MonoBehaviour
{
    [SerializeField] private PlayerView view;
    private PlayerModel _model;
    
    private void Start()
    {
        _model = new PlayerModel();
        _model.OnHealthChanged += () => view.UpdateHealth(_model.Health);
        _model.OnScoreChanged += () => view.UpdateScore(_model.Score);
        
        // Инициализация начальных значений
        view.UpdateHealth(_model.Health);
        view.UpdateScore(_model.Score);
    }
    
    public void TakeDamage(int damage)
    {
        _model.TakeDamage(damage);
    }
    
    public void AddScore(int points)
    {
        _model.AddScore(points);
    }
}