YouTip LogoYouTip

Filter Pattern

# Filter Pattern ## Filter Pattern The Filter Pattern, also known as the Criteria Pattern, is a design pattern that allows developers to filter a set of objects using different criteria, connecting them in a decoupled manner through logical operations. This type of design pattern belongs to the structural pattern category, combining multiple criteria to obtain a single result. * * * ## Overview ### Intent To encapsulate the process of filtering objects, allowing for dynamic filtering of objects using different filtering criteria. ### Main Problem Solved When a set of objects needs to be filtered based on multiple different conditions or criteria, the Filter Pattern provides a flexible way to define these conditions, avoiding the hardcoding of filtering logic in client code. ### Use Cases * When an object collection needs to be filtered based on different criteria. * When the filtering logic may change, or when multiple filtering conditions need to be dynamically combined. ### Implementation Approach * **Define a Filtering Interface**: Create a filtering interface that defines a filtering method. * **Implement Concrete Filters**: Implement the filtering interface for each filtering criterion, encapsulating the specific filtering logic. * **Combine Filters**: Allow filters to be combined to form complex filtering logic. ### Key Code * **Filtering Interface**: Defines the filtering method, such as `matches()`. * **Concrete Filter Class**: Implements the filtering interface, encapsulating specific filtering logic. * **Combined Filter**: Implements the logic for combining filters, such as logical AND, logical OR, etc. ### Application Examples 1. **Library Management System**: Filtering books based on different criteria such as author, publication year, and category. 2. **Online Shopping Platform**: Filtering products based on conditions like price, brand, and user ratings. ### Advantages 1. **Encapsulation**: Filtering logic is encapsulated in independent filter objects. 2. **Flexibility**: Filtering conditions can be dynamically added, modified, or combined. 3. **Extensibility**: Easy to add new filtering criteria without modifying existing code. ### Disadvantages * **Complexity**: As the number of filtering conditions increases, the system may become complex. * **Performance Issues**: If the combination of filters becomes too complex, it may impact performance. ### Usage Recommendations * Consider using the Filter Pattern when the filtering logic may change or when objects need to be dynamically filtered based on different criteria. * During design, ensure that the interface and implementation of the filters remain consistent to facilitate combination and extension. ### Notes * Ensure the combination logic of the filters is correct to avoid introducing logical errors. * During implementation, consider performance impacts, especially when processing large amounts of data. ### Summary The Filter Pattern includes the following main roles: * **Filter Interface (Filter/Criteria)**: Defines an interface for filtering objects. This interface typically contains a method for filtering objects based on specific conditions. * **Concrete Filter Class (Concrete Filter/Concrete Criteria)**: Implements the filter interface, specifically defining the conditions and logic for filtering objects. * **Object Collection (Items/Objects to be filtered)**: The collection of objects to be filtered. These objects are typically instances with common attributes, such as a group of people, a group of products, etc. * **Client**: Uses concrete filter classes to filter the object collection. The client combines the object collection with the filters to obtain objects that meet the criteria. We will create a _Person_ object, a _Criteria_ interface, and entity classes that implement this interface to filter a list of _Person_ objects. The _CriteriaPatternDemo_ class uses _Criteria_ objects to filter the list of _Person_ objects based on various criteria and their combinations. ![Image 1: UML Diagram of the Filter Pattern](#) ### Step 1 Create a class on which the criteria will be applied. ## Person.java ```java public class Person { private String name; private String gender; private String maritalStatus; public Person(String name, String gender, String maritalStatus) { this.name = name; this.gender = gender; this.maritalStatus = maritalStatus; } public String getName() { return name; } public String getGender() { return gender; } public String getMaritalStatus() { return maritalStatus; } } ### Step 2 Create an interface for the criteria. ## Criteria.java ```java import java.util.List; public interface Criteria { public List meetCriteria(List persons); } ### Step 3 Create entity classes that implement the _Criteria_ interface. ## CriteriaMale.java ```java import java.util.ArrayList; import java.util.List; public class CriteriaMale implements Criteria { @Override public List meetCriteria(List persons) { List malePersons = new ArrayList(); for (Person person : persons) { if (person.getGender().equalsIgnoreCase("MALE")) { malePersons.add(person); } } return malePersons; } } ## CriteriaFemale.java ```java import java.util.ArrayList; import java.util.List; public class CriteriaFemale implements Criteria { @Override public List meetCriteria(List persons) { List femalePersons = new ArrayList(); for (Person person : persons) { if (person.getGender().equalsIgnoreCase("FEMALE")) { femalePersons.add(person); } } return femalePersons; } } ## CriteriaSingle.java ```java import java.util.ArrayList; import java.util.List; public class CriteriaSingle implements Criteria { @Override public List meetCriteria(List persons) { List singlePersons = new ArrayList(); for (Person person : persons) { if (person.getMaritalStatus().equalsIgnoreCase("SINGLE")) { singlePersons.add(person); } } return singlePersons; } } ## AndCriteria.java ```java import java.util.List; public class AndCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public AndCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List meetCriteria(List persons) { List firstCriteriaPersons = criteria.meetCriteria(persons); return otherCriteria.meetCriteria(firstCriteriaPersons); } } ## OrCriteria.java ```java import java.util.List; public class OrCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public OrCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List meetCriteria(List persons) { List firstCriteriaItems = criteria.meetCriteria(persons); List otherCriteriaItems = otherCriteria.meetCriteria(persons); for (Person person : otherCriteriaItems) { if (!firstCriteriaItems.contains(person)) { firstCriteriaItems.add(person); } } return firstCriteriaItems; } } ### Step 4 Use different criteria and their combinations to filter the list of _Person_ objects. ## CriteriaPatternDemo.java ```java import java.util.ArrayList; import java.util.List; public class CriteriaPatternDemo { public static void main(String[] args) { List persons = new ArrayList(); persons.add(new Person("Robert", "Male", "Single")); persons.add(new Person("John", "Male", "Married")); persons.add(new Person("Laura", "Female", "Married")); persons.add(new Person("Diana", "Female", "Single")); persons.add(new Person("Mike", "Male", "Single")); persons.add(new Person("Bobby", "Male", "Single")); Criteria male = new CriteriaMale(); Criteria female = new CriteriaFemale(); Criteria single = new CriteriaSingle(); Criteria singleMale = new AndCriteria(single, male); Criteria singleOrFemale = new OrCriteria(single, female); System.out.println("Males: "); printPersons(male.meetCriteria(persons)); System.out.println("nFemales: "); printPersons(female.meetCriteria(persons)); System.out.println("nSingle Males: "); printPersons(singleMale.meetCriteria(persons)); System.out.println("nSingle Or Females: "); printPersons(singleOrFemale.meetCriteria(persons)); } public static void printPersons(List persons) { for (Person person : persons) { System.out.println("Person : [ Name : " + person.getName() + ", Gender : " + person.getGender() + ", Marital Status : " + person.getMaritalStatus() + " ]"); } } } ### Step 5 Execute the program, and the output will be: Males: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : John, Gender : Male, Marital Status : Married ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Females: Person : [ Name : Laura, Gender : Female, Marital Status : Married ] Person : [ Name : Diana, Gender : Female, Marital Status : Single ] Single Males: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Single Or Females: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : Diana, Gender : Female, Marital Status : Single ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
← Composite PatternBridge Pattern β†’