← Назад к вопросам

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

2.2 Middle🔥 111 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерн проектирования в Comparator

Comparator в Java использует два основных паттерна проектирования: Strategy и Functional Object (или Function Object). Эти паттерны позволяют инкапсулировать логику сравнения в отдельный объект.

Паттерн Strategy

Strategy — это поведенческий паттерн, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Comparator — это классический пример этого паттерна.

Как это работает:

  • Контекст — коллекция (List), сортировка которой нужна
  • Strategy (интерфейс)Comparator<T>
  • ConcreteStrategy — различные реализации Comparator
  • Algorithm — логика сравнения элементов
// Strategy интерфейс
public interface Comparator<T> {
    int compare(T o1, T o2);
}

// Context — Collections.sort() или List.sort()
public class Collections {
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        // Используется стратегия сравнения из Comparator
        list.sort(c);
    }
}

// ConcreteStrategy реализации
public class StudentComparators {
    // Strategy 1: сортировка по возрасту
    public static class AgeComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            return Integer.compare(s1.getAge(), s2.getAge());
        }
    }
    
    // Strategy 2: сортировка по имени
    public static class NameComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            return s1.getName().compareTo(s2.getName());
        }
    }
    
    // Strategy 3: сортировка по рейтингу
    public static class RatingComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            return Double.compare(s1.getRating(), s2.getRating());
        }
    }
}

// Использование разных стратегий
public class StrategyExample {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student("Alice", 20, 4.5),
            new Student("Bob", 22, 3.8),
            new Student("Charlie", 19, 4.2)
        );
        
        // Strategy 1: сортировка по возрасту
        Collections.sort(students, new StudentComparators.AgeComparator());
        System.out.println("По возрасту: " + students);
        
        // Strategy 2: сортировка по имени
        Collections.sort(students, new StudentComparators.NameComparator());
        System.out.println("По имени: " + students);
        
        // Strategy 3: сортировка по рейтингу
        Collections.sort(students, new StudentComparators.RatingComparator());
        System.out.println("По рейтингу: " + students);
    }
}

Паттерн Functional Object (Function Object)

Functional Object — это паттерн, при котором объект обёрывает функцию и может быть передан как параметр. В Java 8+ Comparator часто реализуется через Lambda expressions и Method references, что делает его функциональным объектом.

public class FunctionalComparatorExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("banana", "apple", "cherry");
        
        // Functional Object через Lambda
        Comparator<String> byLength = (s1, s2) -> Integer.compare(s1.length(), s2.length());
        words.sort(byLength);
        System.out.println("По длине: " + words);
        
        // Functional Object через Method Reference
        Comparator<String> natural = String::compareTo;
        words.sort(natural);
        System.out.println("По алфавиту: " + words);
    }
}

Практические примеры

Пример 1: Сортировка объектов по разным критериям

public class Person {
    private String name;
    private int age;
    private double salary;
    
    // Getters...
    
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30, 5000),
            new Person("Bob", 25, 4000),
            new Person("Charlie", 35, 6000)
        );
        
        // Strategy 1: по имени (через Comparable)
        people.sort(Comparator.comparing(Person::getName));
        System.out.println("По имени: " + people);
        
        // Strategy 2: по возрасту (через Comparable)
        people.sort(Comparator.comparingInt(Person::getAge));
        System.out.println("По возрасту: " + people);
        
        // Strategy 3: по зарплате в обратном порядке
        people.sort(Comparator.comparingDouble(Person::getSalary).reversed());
        System.out.println("По зарплате (убывание): " + people);
        
        // Strategy 4: комбинированная сортировка
        people.sort(
            Comparator.comparing(Person::getAge)
                .thenComparing(Person::getName)
        );
        System.out.println("По возрасту, затем по имени: " + people);
    }
}

Пример 2: Сложные компараторы

public class AdvancedComparator {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
            new Product("Laptop", 1200, 4.5),
            new Product("Mouse", 25, 4.2),
            new Product("Keyboard", 80, 4.8)
        );
        
        // Сравнитель с использованием собственной логики
        Comparator<Product> customComparator = new Comparator<Product>() {
            @Override
            public int compare(Product p1, Product p2) {
                // Сначала по рейтингу (убывание)
                int ratingCompare = Double.compare(p2.getRating(), p1.getRating());
                if (ratingCompare != 0) {
                    return ratingCompare;
                }
                // Если рейтинг одинаков, то по цене (возрастание)
                return Double.compare(p1.getPrice(), p2.getPrice());
            }
        };
        
        products.sort(customComparator);
        System.out.println("Сортировка: " + products);
    }
}

Преимущества использования Strategy в Comparator

  • Гибкость — можно легко менять способ сравнения без изменения алгоритма сортировки
  • Переиспользование — одна стратегия может быть использована в разных местах
  • Расширяемость — легко добавить новые стратегии сравнения
  • Читаемость — логика сравнения инкапсулирована в отдельный класс

Сравнение Strategy и Comparable

public class ComparisonExample {
    // Comparable — встроенный порядок сортировки
    public class Student implements Comparable<Student> {
        @Override
        public int compareTo(Student other) {
            return this.age - other.age; // Фиксированный порядок по возрасту
        }
    }
    
    // Comparator — гибкий способ сравнения
    public static Comparator<Student> compareByName = 
        Comparator.comparing(s -> s.name);
    public static Comparator<Student> compareByAge = 
        Comparator.comparing(s -> s.age);
}

Заключение

Comparator использует паттерн Strategy, позволяя инкапсулировать различные логики сравнения в отдельные объекты. Это паттерн обеспечивает гибкость и позволяет выбирать способ сортировки во время выполнения программы. В Java 8+ Comparator также часто рассматривается как Functional Object, особенно при использовании Lambda expressions.

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