Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ComperatorFactory using static methods or each in its own class?

I was thinking of implementing multiple Comperators. Now I am not sure about how to do this in a most favourable way, i.e. still having the ability to do dependency injection.

Method 1: One class is one comparator (as seen in this answer):

// file LexicographicComparator.java
class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

// file AgeComparator.java
class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

Method 2: Now it would surely be possible to do sth like this:

class PersonComperatorFactory {
    public static Comparator<Person> getAgeComparator() {
        return new Comparator<Person>() {
            @Override
            public int compare(Person a, Person b) {
                return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
            }
        }
    }
    
    public static Comparator<Person> getLexicographicComparator() {
        return new Comparator<Person>() {
            @Override
            public int compare(Person a, Person b) {
                return a.name.compareToIgnoreCase(b.name);
            }
        }
    }
}

The second method is surely less cluttering your packages (put it to the .domain package or .util package? Or create a new .domain.comperators package?). But is this a good idea at all? I mean, does this have any benefits besides less files? What about code reusage, or DependencyInjection - may it have drawbacks I am yet unable to see?

I'd like this to be not a "chose your favourite"-question, but there may be many good reasons why to use one or the other.

Thank you very much in advance.

PS: In which package would you put this (this is probably a personal choice)? But this is only a side-question suitable for a comment.

like image 357
Benjamin Marwell Avatar asked Mar 14 '23 14:03

Benjamin Marwell


2 Answers

In my opinion the best way to achieve the desidered result is to have an utility class (putting it in .util package) containing all your static comparators.

Example:

public class Comparators {
    public static final Comparator<Person> PERSON_LEXICOGRAPHIC_COMPARATOR = new Comparator<Person>() {
        @Override
        public int compare(Person a, Person b) {
            return a.name.compareToIgnoreCase(b.name);
        }
    }

    public static final Comparator<Person> PERSON_AGE_COMPARATOR = new Comparator<Person>() {
        @Override
        public int compare(Person a, Person b) {
            return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
        }
    }
}

Or in the Java 8 way:

public class Comparators {
    public static final Comparator<Person> PERSON_LEXICOGRAPHIC_COMPARATOR = (Person a, Person b) -> a.name.compareToIgnoreCase(b.name);
    public static final Comparator<Person> PERSON_AGE_COMPARATOR = (Person a, Person b) -> (a.age < b.age ? -1 : a.age == b.age ? 0 : 1);
}

I would use directly the static instances in order to do not waste memory and resources, since they do not use any state attribute in the compare method.

like image 102
Francesco Pitzalis Avatar answered Apr 07 '23 16:04

Francesco Pitzalis


IMHO the best way is a mix because you have a single entry point to get all your comparators (you don't need to know name of each comparator: all are in the same java class) and you can instantiate all your comparators as a bean.

public class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

// file AgeComparator.java
public class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

public class PersonComperatorFactory {

    private static final Comparator<Person> NAME_COMPARATOR = new LexicographicComparator();       
    private static final Comparator<Person> AGE_COMPARATOR = new AgeComparator();

    public static Comparator<Person> getLexicographicComparator() {
        return NAME_COMPARATOR;
    }

    public static Comparator<Person> getAgeComparator() {
        return AGE_COMPARATOR;
    }
}
like image 23
Sergiy Medvynskyy Avatar answered Apr 07 '23 18:04

Sergiy Medvynskyy