Having a list of filters outsourced is not very suitable for solving your problem. Each filter depends on different types of parameters that must be passed to the doFilter method. The need for this makes the approach very inflexible. Yes, you can use varargs, but it will just create a mess. That's why it is probably easier to implement the builder to create a whole chain of filters to apply to a collection of products. Adding new filters to the constructor becomes a trivial task. The Builder pattern is very useful when many different parameters are played.
Consider this interface:
public interface CollectionFilter<T> { public Collection<T> doFilter(Collection<T> collection); }
A filter chain class that applies all filters to a collection:
public class CollectionFilterChain<T> { private final List<CollectionFilter<T>> filters; public CollectionFilterChain(List<CollectionFilter<T>> filters) { this.filters = filters; } public Collection<T> doFilter(Collection<T> collection) { for (CollectionFilter<T> filter : filters) { collection = filter.doFilter(collection); } return collection; } }
Two implementations of CollectionFilter<T> :
public class InStockFilter<T> implements CollectionFilter<T> { public Collection<T> doFilter(Collection<T> collection) { // filter } } public class MinPriceFilter<T> implements CollectionFilter<T> { private final float minPrice; public MinPriceFilter(float minPrice) { this.minPrice = minPrice; } public Collection<T> doFilter(Collection<T> collection) { // filter } }
And a creator that allows you to easily create a filter chain:
public class CollectionFilterChainBuilder<T> { List<CollectionFilter<T>> filters; public CollectionFilterChainBuilder() { filters = new ArrayList<CollectionFilter<T>>(); } public CollectionFilterChainBuilder<T> inStock() { filters.add(new InStockFilter<T>()); return this; } public CollectionFilterChainBuilder<T> minPrice(float price) { filters.add(new MinPriceFilter<T>(price)); return this; } public CollectionFilterChain<T> build() { return new CollectionFilterChain<T>(filters); } }
Using the builder, it's easy to create a filter chain as follows:
CollectionFilterChainBuilder<Product> builder = new CollectionFilterChainBuilder(); CollectionFilterChain<Product> filterChain = builder.inStock().minPrice(2.0f).build(); Collection<Product> filteredProducts = filterChain.doFilter(products);
In more dynamic settings, you can use the builder, for example:
CollectionFilterChainBuilder<Product> builder = new CollectionFilterChainBuilder(); if (filterInStock) { builder.inStock(); } if (filterMinPrice) { builder.minPrice(minPrice); }
source share