patternjavaMinor
Class that represents searchable and sortable elements
Viewed 0 times
sortableelementssearchablethatandclassrepresents
Problem
In my application, I have a small hierarchy of related classes (partner categories - partners - partner points).
The application has two representations of its content:
The application has the filters for searching and sorting. The map used only the search filters, but in the list used both types of filters.
Please, criticize my code and help me choose a proper name instead of
This class was written using TDD.
SearchableSortable.java
```
public class SearchableSortable implements Serializable {
public static interface OnEachHandler {
void onEach(T each, boolean meetsCriteria);
}
public static interface SearchCriteria {
boolean meetCriteria(T obj);
}
private final List elements;
private final List> searchCriterias;
private final List> comparators;
public static SearchableSortable newInstance(Collection elements) {
return new SearchableSortable(elements);
}
private SearchableSortable(Collection elements) {
this.elements = new ArrayList(elements);
this.searchCriterias = new ArrayList>();
this.comparators = new ArrayList>();
}
public void addSearchCriteria(SearchCriteria searchCriteria) {
searchCriterias.add(searchCriteria);
}
public void addComparator(Comparator comparator) {
comparators.add(comparator);
}
public void clear() {
searchCriterias.clear();
comparators.clear();
}
public void forEach(OnEachHandler onEachHandler) {
for (T each : elements) {
onEachHandler.onEach(each, meetCriteria(each));
}
}
private boolean meetCriteria(T element) {
for (SearchCriteria searchCriteria : searchCriterias) {
if (!searchCriteria.meetCriteria(element)) {
return false;
}
}
retu
The application has two representations of its content:
- in the form of partners points on the map
- in the form of a list of partner categories or partners within a category
The application has the filters for searching and sorting. The map used only the search filters, but in the list used both types of filters.
Please, criticize my code and help me choose a proper name instead of
SearchableSortable.This class was written using TDD.
SearchableSortable.java
```
public class SearchableSortable implements Serializable {
public static interface OnEachHandler {
void onEach(T each, boolean meetsCriteria);
}
public static interface SearchCriteria {
boolean meetCriteria(T obj);
}
private final List elements;
private final List> searchCriterias;
private final List> comparators;
public static SearchableSortable newInstance(Collection elements) {
return new SearchableSortable(elements);
}
private SearchableSortable(Collection elements) {
this.elements = new ArrayList(elements);
this.searchCriterias = new ArrayList>();
this.comparators = new ArrayList>();
}
public void addSearchCriteria(SearchCriteria searchCriteria) {
searchCriterias.add(searchCriteria);
}
public void addComparator(Comparator comparator) {
comparators.add(comparator);
}
public void clear() {
searchCriterias.clear();
comparators.clear();
}
public void forEach(OnEachHandler onEachHandler) {
for (T each : elements) {
onEachHandler.onEach(each, meetCriteria(each));
}
}
private boolean meetCriteria(T element) {
for (SearchCriteria searchCriteria : searchCriterias) {
if (!searchCriteria.meetCriteria(element)) {
return false;
}
}
retu
Solution
Your class feels wrongly named. The first sign of a problem is that "-able" and "-ible" suffixes are generally used for interfaces rather than classes. Let's see what it is really trying to do:
-
It associates several search criteria with the collection (
By the way, criterion is singular ; criteria is its plural form.
I would call the class
The search criteria and comparator seem like they should be more intimately related. For example, if you search for partners located within n kilometers of a location, that implies that you also want to rank the search results by distance.
My suggestion for an interface would be:
Example usage:
One main difference, which may be either an advantage or disadvantage, is that you would avoid having multiple unmanaged
That's just a suggestion; you'll probably have to adapt it for your situation as appropriate.
- It represents an ordered collection of objects of type
T(private final List elements)
-
It associates several search criteria with the collection (
private final List> searchCriterias)By the way, criterion is singular ; criteria is its plural form.
- It associates several sorting keys with the collection (
private final List> comparators)
I would call the class
SearchableListing. I chose "listing" instead of "list" because it merely helps enumerate the items in the list; the class does not actually extend List. I would leave "sortable" out of the name, as "listing" somewhat implies that the search results can be ordered by relevance.The search criteria and comparator seem like they should be more intimately related. For example, if you search for partners located within n kilometers of a location, that implies that you also want to rank the search results by distance.
My suggestion for an interface would be:
public class SearchableListing implements Iterable {
public static interface Criterion extends Comparator {
public boolean filter(T t);
}
/**
* Iterator that produces all elements that meet the search criteria,
* sorted by the natural ordering for those search criteria.
*/
private class ResultIterator implements Iterator {
public ResultIterator(List list, List crit) {
}
@Override
public void remove() { throw new UnsupportedOperationException(); }
@Override
public boolean hasNext() { /* TODO */ }
@Override
public T next() { /* TODO */ }
}
private Collection elements;
private List criteria;
public void SearchableListing(Collection elements) { /* TODO */ }
public void addCriterion(Criterion c) { /* TODO */ }
@Override
public Iterator iterator() {
return new ResultIterator(this.list, this.criteria);
}
}Example usage:
List partners = getPartners();
SearchableListing partnerListing = new SearchableListing(partners);
partnerListing.addCriterion(new DistanceFromPoint(here));
for (Partner p : partnerListing) {
// Do stuff with p
}One main difference, which may be either an advantage or disadvantage, is that you would avoid having multiple unmanaged
Lists floating around, as the caller is forced to enumerate the results using your class. That's just a suggestion; you'll probably have to adapt it for your situation as appropriate.
Code Snippets
public class SearchableListing<T> implements Iterable<T> {
public static interface Criterion<T> extends Comparator<T> {
public boolean filter(T t);
}
/**
* Iterator that produces all elements that meet the search criteria,
* sorted by the natural ordering for those search criteria.
*/
private class ResultIterator<T> implements Iterator<T> {
public ResultIterator(List<T> list, List<Criterion> crit) {
}
@Override
public void remove() { throw new UnsupportedOperationException(); }
@Override
public boolean hasNext() { /* TODO */ }
@Override
public T next() { /* TODO */ }
}
private Collection<T> elements;
private List<Criterion> criteria;
public void SearchableListing(Collection<T> elements) { /* TODO */ }
public void addCriterion(Criterion c) { /* TODO */ }
@Override
public Iterator<T> iterator() {
return new ResultIterator<T>(this.list, this.criteria);
}
}List<Partner> partners = getPartners();
SearchableListing<Partner> partnerListing = new SearchableListing(partners);
partnerListing.addCriterion(new DistanceFromPoint(here));
for (Partner p : partnerListing) {
// Do stuff with p
}Context
StackExchange Code Review Q#39641, answer score: 3
Revisions (0)
No revisions yet.