Какой паттерн проектирования реализует интерфейс Comparator?

Ответ

Интерфейс java.util.Comparator — это прямая реализация паттерна Strategy (Стратегия).

Суть паттерна: Вынести изменяемый алгоритм (правило сравнения) в отдельный объект, чтобы можно было выбирать и подменять его независимо от клиента, который этот алгоритм использует.

Пример с Comparator:

List<Employee> employees = getEmployees();

// Стратегия 1: Сортировка по имени
Comparator<Employee> byName = Comparator.comparing(Employee::getName);
employees.sort(byName);

// Стратегия 2: Сортировка по зарплате (по убыванию)
Comparator<Employee> bySalaryDesc = Comparator.comparingInt(Employee::getSalary).reversed();
employees.sort(bySalaryDesc);

// Стратегия 3: Композиция стратегий (сначала по отделу, затем по имени)
Comparator<Employee> byDeptThenName =
        Comparator.comparing(Employee::getDepartment)
                  .thenComparing(Employee::getName);
employees.sort(byDeptThenName);

Преимущества такого подхода в контексте Comparator:

  • SRP (Single Responsibility Principle): Класс Employee не знает о способах своего сравнения.
  • Открытость/закрытость: Новые правила сортировки добавляются созданием новых классов-стратегий без модификации существующего кода.
  • Тестируемость: Стратегию сравнения легко протестировать изолированно.
  • Повторное использование: Одна стратегия сравнения может применяться к разным коллекциям.

Ответ 18+ 🔞

А, слушай, смотри, вот этот твой java.util.Comparator — это же чистейший, блядь, паттерн Strategy (Стратегия), в натуре!

В чём соль, ёпта: Берёшь этот твой изменчивый алгоритм — в нашем случае, правило, как хуярить сравнение — и выносишь его в отдельный объект. И теперь ты можешь его подменять, как перчатки, а основной код, который им пользуется, даже не заметит подмены. Хитрая жопа, да?

Смотри, как это в коде выглядит, прям как в жизни:

List<Employee> employees = getEmployees();

// Стратегия первая, классика: сортируем по имени, как в телефонной книге
Comparator<Employee> byName = Comparator.comparing(Employee::getName);
employees.sort(byName);

// Стратегия вторая, материальная: по зарплате, но наоборот, от жирной к тощей
Comparator<Employee> bySalaryDesc = Comparator.comparingInt(Employee::getSalary).reversed();
employees.sort(bySalaryDesc);

// Стратегия третья, комбинированная: сначала по отделу, а там, где отдел одинаковый — уже по имени, чтоб без бардака
Comparator<Employee> byDeptThenName =
        Comparator.comparing(Employee::getDepartment)
                  .thenComparing(Employee::getName);
employees.sort(byDeptThenName);

И что мы, сука, с этого имеем, а?

  • Принцип единственной ответственности (SRP): Сам класс Employee теперь не парится, как его сравнивать. Он просто работяга, а не стратег, блядь.
  • Открытость/закрытость: Захотел новое правило сортировки — написал новую стратегию. Старый код даже не чихнул, ему похуй. Красота!
  • Тестируемость: Каждую стратегию можно отъебашить тестами по отдельности, не трогая весь остальной цирк.
  • Повторное использование: Написал один раз компаратор для сравнения, например, по дате — и потом тыкай его куда угодно, в разные списки. Удобно, ёпта!