Примеры кода
Принцип единственной ответственности (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);
}
}