Java Encapsulation – Does the Use of Comparator Interface Break Encapsulation?

javaobject-oriented

According to the essay "The Object Calisthenics" by Jeff Bay in the book ThoughtWorks Anthology,
Use of Getters and Setters should be avoided as they break encapsulation and we should instead ask the object to do something for us instead of digging in to the object and getting its fields.

how about comparison of objects ?

I have to find best object say a Resort for the customer on the basis of a rule that uses few properties of the Resort object.

This rule can change in future.
So I find use of comparator interface better as compared to comparable interface.
But then I will have to use getters and setters for to access individual properties to compare to objects in a different class.

Best Answer

Books can be wrong or misleading. It is certainly true that having getters and setters for every field provides little more encapsulation than having those fields be public, and it's unfortunate that this kind of design is very widespread.

But it's nonsense to conclude that getters and setters should be avoided altogether. Instead, they should be added deliberately where appropriate, as part of the API design of the class:

  1. If everything a field does can be handled by domain-specific methods, don't have a getter or setter - this is the best case.
  2. If the value of a field is by itself useful and necessary for other classes, add a getter (not a setter)
  3. If the fields represents something like a configuration value, a way for the behaviour of the object to be influenced from outside, add a setter (and a getter iff knowing this configuration could also be useful to other classes).

A Comparator could be seen as an example for case 2, especially if the Comparator is deliberately used instead of having the class implement Comparable. This indicates that the comparison logic is external to the class, and it depends on the field, so the field is useful outside the class.

A compromise might be to have a package private (default visibility) getter and keep the comparator in the same package - or even have it as an inner class that accesses the private field. That would be appropriate if you want the class itself to offer a choice of different sort orders.

If your only concern is that the sort order may change globally in the future, I'd actually stay with Comparable - it's still a change in once place, no need to separate it artificially.