Могут ли классические паттерны проектирования нарушать принципы SOLID?

«Могут ли классические паттерны проектирования нарушать принципы SOLID?» — вопрос из категории Паттерны, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, при некорректном или догматичном применении паттерны могут нарушать принципы SOLID. Ключевая проблема — не сам паттерн, а его реализация.

Примеры потенциальных нарушений:

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

    • Нарушает SRP (Single Responsibility): Класс управляет своим жизненным циклом и содержит бизнес-логику.
    • Нарушает DIP (Dependency Inversion): Жесткая привязка к глобальному экземпляру (shared), что усложняет тестирование.

      class AppSettings { // Проблемная реализация
      static let shared = AppSettings()
      private init() {}
      
      var theme: Theme = .light
      // Нарушение SRP: ниже смешана логика
      func saveToDisk() { /* ... */ }
      func validate() -> Bool { /* ... */ }
      }
  2. Factory Method (Фабричный метод):

    • Может нарушать OCP (Open/Closed): Если для добавления нового типа продукта требуется модифицировать базовый класс фабрики, а не расширять его.
  3. Decorator (Декоратор):

    • Может нарушать SRP и ISP (Interface Segregation): Если декоратор добавляет множество несвязанных функций, превращаясь в "божественный объект", или если он вынужден реализовывать неиспользуемые методы большого интерфейса.

Как избежать нарушений:

  • Singleton: Использовать Dependency Injection, передавая экземпляр как зависимость. Ограничить ответственность Singleton'а только управлением экземпляром (например, через абстракцию ConfigStorage).
  • Factory Method: Использовать абстрактную фабрику или регистрацию продуктов, чтобы система была открыта для расширения.
  • Общее правило: Адаптировать паттерн под контекст, отдавая приоритет принципам гибкого и поддерживаемого кода, а не буквальному следованию диаграмме.