Какие основные паттерны проектирования вы знаете?

«Какие основные паттерны проектирования вы знаете?» — вопрос из категории Архитектура, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

1. Порождающие паттерны (Creational)

Управляют процессом создания объектов, делая его более гибким и независимым.

  • Singleton (Одиночка): Гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.
    public class Singleton {
        private static Singleton instance;
        private Singleton() {} // Приватный конструктор
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
  • Factory Method (Фабричный метод): Определяет интерфейс для создания объекта, но позволяет подклассам изменять тип создаваемого объекта.
  • Abstract Factory (Абстрактная фабрика): Создает семейства связанных объектов без указания их конкретных классов.
  • Builder (Строитель): Позволяет создавать сложные объекты пошагово, отделяя конструирование от представления.

2. Структурные паттерны (Structural)

Объясняют, как собирать объекты и классы в более крупные структуры, сохраняя гибкость и эффективность.

  • Adapter (Адаптер): Позволяет объектам с несовместимыми интерфейсами работать вместе.
  • Decorator (Декоратор): Динамически добавляет объекту новые обязанности, являясь гибкой альтернативой наследованию.

    class Coffee:
        def cost(self): return 5
    
    class MilkDecorator:
        def __init__(self, coffee):
            self._coffee = coffee
        def cost(self):
            return self._coffee.cost() + 2
    
    my_coffee = Coffee()
    my_coffee_with_milk = MilkDecorator(my_coffee)
    print(my_coffee_with_milk.cost()) # Вывод: 7
  • Facade (Фасад): Предоставляет простой интерфейс к сложной подсистеме.
  • Proxy (Заместитель): Является суррогатом или placeholder другого объекта для контроля доступа к нему.

3. Поведенческие паттерны (Behavioral)

Решают задачи эффективного взаимодействия и распределения ответственности между объектами.

  • Observer (Наблюдатель): Определяет зависимость «один-ко-многим» между объектами так, что при изменении состояния одного объекта все зависящие от него объекты уведомляются.
  • Strategy (Стратегия): Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
  • Command (Команда): Инкапсулирует запрос как объект, позволяя параметризовать клиенты с различными запросами, ставить их в очередь или логировать.

Зачем это тестировщику?

Понимание паттернов помогает:

  1. Анализировать архитектуру: Быстрее разобраться в коде и логике приложения.
  2. Проектировать тесты: Предсказывать точки взаимодействия и потенциальные дефекты (например, состояние гонки в Singleton, неверная настройка Strategy).
  3. Общаться с разработчиками: Использовать общий словарь для обсуждения решений и проблем.