You haven't said whether the filters take any parameters. For example, filter_A
might be a category filter, so that it's not just a question of "do I need to apply filter_A
", it could be "I need to apply filter_A
and return all records in with the category field = fooCategory
".
The simplest way to implement exactly what you've described (but make sure to read the second half of the answer below) is similar to the other answers, but I wouldn't have any boolean checks at all. I would define interfaces: FilterA, FilterB, FilterC
. Then you can have something like (I'm a Java programmer, so this will be Java-esque syntax):
class RequestFilters {
FilterA filterA;
FilterB filterB;
FilterC filterC;
}
Then you could have something like this (using the enum singleton pattern from Effective Java):
enum NoOpFilterA implements FilterA {
INSTANCE;
public List<Item> applyFilter(List<Item> input) {
return input;
}
}
But if you actually want some items to be filtered, you can instead provide an instance of a FilterA
implementation that actually does something. Your filtration method will be the very simple
List<Item> filterItems(List<Item> data, RequestFilters filters) {
List<Item> returnedList = data;
returnedList = filters.filterA.filter(data);
returnedList = filters.filterB.filter(data);
returnedList = filters.filterC.filter(data);
return returnedList;
}
But I'm just getting started.
I suspect that the applyFilter
call will actually be quite similar for all three types of filters. If that's the case, I wouldn't even do it the way described above. You can get even cleaner code by only having one interface, then doing this:
class ChainedFilter implements Filter {
List<Filter> filterList;
void addFilter(Filter filter) {
filterList.add(filter);
}
List<Item> applyFilter(List<Item> input) {
List<Item> returnedList = input;
for(Filter f : filterList) {
returnedList = f.applyFilter(returnedList);
}
return returnedList;
}
}
Then, as your user navigates through the pages, you just add a new instance of whatever filter you need when appropriate. This will allow you to be able to apply multiple instances of the same filter with different arguments should you need that behavior in the future, and also add additional filters in the future without having to change your design.
Additionally, you can add either something like the NoOpFilter
above or you can just not add a particular filter at all to the list, whatever is easier for your code.
filter_C
, but the conditional statements indicate that control flow can go aroundfilter_C
. Isfilter_C
optional?