Ответ
Интерфейс 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теперь не парится, как его сравнивать. Он просто работяга, а не стратег, блядь. - Открытость/закрытость: Захотел новое правило сортировки — написал новую стратегию. Старый код даже не чихнул, ему похуй. Красота!
- Тестируемость: Каждую стратегию можно отъебашить тестами по отдельности, не трогая весь остальной цирк.
- Повторное использование: Написал один раз компаратор для сравнения, например, по дате — и потом тыкай его куда угодно, в разные списки. Удобно, ёпта!