Изучал ли паттерны?

«Изучал ли паттерны?» — вопрос из категории Паттерны, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

  • Писать более поддерживаемый и гибкий код.
  • Эффективнее общаться с коллегами, используя общепринятые названия ("используем Фабрику", "здесь нужен Стратегия").
  • Избегать типичных архитектурных ошибок.

Практический пример из C#: Допустим, нужно реализовать систему логирования, которая может выводить сообщения в консоль, файл или отправлять по сети. Прямой подход с условными операторами быстро становится громоздким.

Применение паттерна Стратегия (Strategy):

// 1. Общий интерфейс для всех алгоритмов логирования
public interface ILogger
{
    void Log(string message);
}

// 2. Конкретные реализации (стратегии)
public class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine($"[CONSOLE] {message}");
}

public class FileLogger : ILogger
{
    private readonly string _filePath;
    public FileLogger(string filePath) => _filePath = filePath;
    public void Log(string message) => File.AppendAllText(_filePath, $"[FILE] {message}n");
}

// 3. Контекст, который использует стратегию
public class Application
{
    private readonly ILogger _logger;
    // Внедрение зависимости через конструктор (это тоже паттерн)
    public Application(ILogger logger) => _logger = logger;

    public void Run()
    {
        _logger.Log("Запуск приложения...");
        // Логика приложения
    }
}

// 4. Использование
var appWithConsoleLog = new Application(new ConsoleLogger());
var appWithFileLog = new Application(new FileLogger("log.txt"));

appWithConsoleLog.Run();
appWithFileLog.Run();

Почему это хорошо? Код Application теперь не зависит от конкретных классов логирования. Мы можем легко добавлять новые способы логирования (например, NetworkLogger), не изменяя существующий код Application — это следует принципу открытости/закрытости (Open/Closed Principle). Чаще всего я использую порождающие паттерны (Фабрика, Singleton через DI) для создания объектов и структурные (Адаптер, Компоновщик) для построения гибких иерархий.