让我们讨论另一个非常有用的设计模式-过滤器设计模式。
过滤器设计模式
为了直接了解对象集合上的过滤模式,让我们使用在《Builder Design Pattern》一文中使用的Employee类。完全不需要使用构建器进行过滤。我们需要的只是一组要过滤的对象。我只是为了节省一些时间来编写一个好的POJO类以进行收集并做一些很好的过滤示例。希望你能理解。
使用筛选器设计模式的员工收集筛选器 这是Employee类的代码:
package org.trishinfotech.filter; public class Employee { private int empNo; private String name; private Gender gender; private Deptt depttName; private int salary; private int mgrEmpNo; private String projectName; public Employee(EmployeeBuilder employeeBuilder) { if (employeeBuilder == null) { throw new IllegalArgumentException("Please provide employee builder to build employee object."); } if (employeeBuilder.empNo <= 0) { throw new IllegalArgumentException("Please provide valid employee number."); } if (employeeBuilder.name == null || employeeBuilder.name.trim().isEmpty()) { throw new IllegalArgumentException("Please provide employee name."); } this.empNo = employeeBuilder.empNo; this.name = employeeBuilder.name; this.gender = employeeBuilder.gender; this.depttName = employeeBuilder.depttName; this.salary = employeeBuilder.salary; this.mgrEmpNo = employeeBuilder.mgrEmpNo; this.projectName = employeeBuilder.projectName; } public int getEmpNo() { return empNo; } public String getName() { return name; } public Gender getGender() { return gender; } public Deptt getDepttName() { return depttName; } public int getSalary() { return salary; } public int getMgrEmpNo() { return mgrEmpNo; } public String getProjectName() { return projectName; } @Override public String toString() { // StringBuilder class also uses Builder Design Pattern with implementation of // java.lang.Appendable interface StringBuilder builder = new StringBuilder(); builder.append("Employee [empNo=").append(empNo).append(", name=").append(name).append(", gender=") .append(gender).append(", depttName=").append(depttName).append(", salary=").append(salary) .append(", mgrEmpNo=").append(mgrEmpNo).append(", projectName=").append(projectName).append("]"); return builder.toString(); } public static class EmployeeBuilder { private int empNo; protected String name; protected Gender gender; protected Deptt depttName; protected int salary; protected int mgrEmpNo; protected String projectName; public EmployeeBuilder() { super(); } public EmployeeBuilder empNo(int empNo) { this.empNo = empNo; return this; } public EmployeeBuilder name(String name) { this.name = name; return this; } public EmployeeBuilder gender(Gender gender) { this.gender = gender; return this; } public EmployeeBuilder depttName(Deptt depttName) { this.depttName = depttName; return this; } public EmployeeBuilder salary(int salary) { this.salary = salary; return this; } public EmployeeBuilder mgrEmpNo(int mgrEmpNo) { this.mgrEmpNo = mgrEmpNo; return this; } public EmployeeBuilder projectName(String projectName) { this.projectName = projectName; return this; } public Employee build() { Employee emp = null; if (validateEmployee()) { emp = new Employee(this); } else { System.out.println("Sorry! Employee objects can't be build without required details"); } return emp; } private boolean validateEmployee() { return (empNo > 0 && name != null && !name.trim().isEmpty()); } } }
我添加了 性别字段,还将depttName更改为枚举,以清楚地编写过滤条件。因此,我们还要定义枚举。
这是性别枚举的代码:
package org.trishinfotech.filter; public enum Gender { MALE, FEMALE; }
这是Deptt枚举的代码:
package org.trishinfotech.filter; public enum Deptt { ENG, QA, HR, SUPPORT, IT, ADMIN }
示例1:通过使用筛选器为整个集合 这样,我们接受整个集合,并通过消除根据过滤条件不适用的成员来返回集合。
现在,让我们编写一个名为Filter 的接口来实现不同的过滤条件或条件:
package org.trishinfotech.filter; import java.util.List; public interface Filter { public List<Employee> apply(List<Employee> employees); }
这是MaleFilter类的代码:
package org.trishinfotech.filter.example1; import java.util.ArrayList; import java.util.List; import org.trishinfotech.filter.Employee; import org.trishinfotech.filter.Gender; public class MaleFilter implements Filter { @Override public List<Employee> apply(List<Employee> employees) { // implementing in old way List<Employee> filteredEmployees = new ArrayList<Employee>(); if (employees != null) { for (Employee employee : employees) { if (Gender.MALE.equals(employee.getGender())) { filteredEmployees.add(employee); } } } return filteredEmployees; } }
这是EngFilter类的代码:
package org.trishinfotech.filter.example1; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.trishinfotech.filter.Deptt; import org.trishinfotech.filter.Employee; public class EngFilter implements Filter { @Override public List<Employee> apply(List<Employee> employees) { List<Employee> filteredEmployees = new ArrayList<Employee>(); // implementing using lambda expressions if (employees != null) { filteredEmployees.addAll(employees.stream().filter(employee -> Deptt.ENG.equals(employee.getDepttName())) .collect(Collectors.toList())); } return filteredEmployees; } }
让我们再写两个过滤器,以通过' And Condition'或' Or Condition'组合任何两个过滤器。
这是AndFilter类的代码:
package org.trishinfotech.filter.example1; import java.util.List; import org.trishinfotech.filter.Employee; public class AndFilter implements Filter { private Filter filter; private Filter anotherFilter; public AndFilter(Filter filter, Filter anotherFilter) { this.filter = filter; this.anotherFilter = anotherFilter; } @Override public List<Employee> apply(List<Employee> employees) { List<Employee> firstFilteredEmployees = filter.apply(employees); List<Employee> secondFilterEmployees = anotherFilter.apply(firstFilteredEmployees); return secondFilterEmployees; } }
这是OrFilter类的代码:
package org.trishinfotech.filter.example1; import java.util.ArrayList; import java.util.List; import org.trishinfotech.filter.Employee; public class OrFilter implements Filter { private Filter filter; private Filter anotherFilter; public OrFilter(Filter Filter, Filter anotherFilter) { this.filter = Filter; this.anotherFilter = anotherFilter; } @Override public List<Employee> apply(List<Employee> employees) { List<Employee> firstFilteredEmployees = filter.apply(employees); List<Employee> secondFilterEmployees = anotherFilter.apply(firstFilteredEmployees); // now lets make or Filter. // first copy all first Filter filtered employees. // now add all second Filter filtered employees which are NOT already in the list // via first Filter employees. List<Employee> orFilteredEmployees = new ArrayList<Employee>(firstFilteredEmployees); secondFilterEmployees.removeAll(firstFilteredEmployees); orFilteredEmployees.addAll(secondFilterEmployees); return orFilteredEmployees; } }
现在让我们编写Main 类来执行和测试输出:
package org.trishinfotech.filter.example1; import java.util.Arrays; import java.util.List; import org.trishinfotech.filter.Deptt; import org.trishinfotech.filter.Employee; import org.trishinfotech.filter.Gender; public class Main { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee.EmployeeBuilder().empNo(101).name("Brijesh").gender(Gender.MALE).depttName(Deptt.ENG .salary(140000).projectName("Builder Pattern").build(), new Employee.EmployeeBuilder().empNo(102).name("Racheal").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(90000).projectName("Factory Pattern").build(), new Employee.EmployeeBuilder().empNo(103).name("Kim").gender(Gender.MALE).depttName(Deptt.HR) .salary(150000).projectName("Editorial").build(), new Employee.EmployeeBuilder().empNo(104).name("Micheal").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(80000).projectName("Decorator Pattern").build(), new Employee.EmployeeBuilder().empNo(105).name("Martin").gender(Gender.MALE).depttName(Deptt.SUPPORT) .salary(65000).projectName("Web Management").build(), new Employee.EmployeeBuilder().empNo(106).name("Pierce").gender(Gender.MALE).depttName(Deptt.HR) .salary(130000).projectName("Audit").build(), new Employee.EmployeeBuilder().empNo(107).name("Anjali").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(60000).projectName("State Pattern").build(), new Employee.EmployeeBuilder().empNo(108).name("Angelina").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(70000).projectName("Flyweight Pattern").build(), new Employee.EmployeeBuilder().empNo(109).name("Hemant").gender(Gender.MALE).depttName(Deptt.HR) .salary(170000).projectName("Audit").build(), new Employee.EmployeeBuilder().empNo(110).name("Mike").gender(Gender.MALE).depttName(Deptt.IT) .salary(150000).projectName("Networking").build()); System.out.println("Print all employees..."); printEmployees(employees); List<Employee> maleEmployees = (new MaleFilter().apply(employees)); System.out.println("Print all Male employees..."); printEmployees(maleEmployees); List<Employee> maleEngEmployees = (new AndFilter(new MaleFilter(), new EngFilter()).apply(employees)); System.out.println("Print all Male And ENG employees..."); printEmployees(maleEngEmployees); } private static void printEmployees(List<Employee> employees) { System.out.println("======================================================================"); employees.stream().forEach(employee -> System.out.println(employee)); System.out.println("======================================================================"); } }
以下是输出:
Print all employees... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=102, name=Racheal, gender=FEMALE, depttName=ENG, salary=90000, mgrEmpNo=0, projectName=Factory Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=104, name=Micheal, gender=FEMALE, depttName=ENG, salary=80000, mgrEmpNo=0, projectName=Decorator Pattern] Employee [empNo=105, name=Martin, gender=MALE, depttName=SUPPORT, salary=65000, mgrEmpNo=0, projectName=Web Management] Employee [empNo=106, name=Pierce, gender=MALE, depttName=HR, salary=130000, mgrEmpNo=0, projectName=Audit] Employee [empNo=107, name=Anjali, gender=FEMALE, depttName=ENG, salary=60000, mgrEmpNo=0, projectName=State Pattern] Employee [empNo=108, name=Angelina, gender=FEMALE, depttName=ENG, salary=70000, mgrEmpNo=0, projectName=Flyweight Pattern] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== Print all Male employees... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=105, name=Martin, gender=MALE, depttName=SUPPORT, salary=65000, mgrEmpNo=0, projectName=Web Management] Employee [empNo=106, name=Pierce, gender=MALE, depttName=HR, salary=130000, mgrEmpNo=0, projectName=Audit] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== Print all Male And ENG employees... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] ======================================================================
示例2:通过使用筛选器为集合的单个成员 通过这种方式,我们在过滤器中接受集合的成员,并对其进行验证以了解该成员是否满足过滤器条件或条件。
这是Filter接口的代码:
package org.trishinfotech.filter.example2; import org.trishinfotech.filter.Employee; public interface Filter { public boolean apply(Employee employees); }
package org.trishinfotech.filter.example2; import org.trishinfotech.filter.Employee; import org.trishinfotech.filter.Gender; public class MaleFilter implements Filter { @Override public boolean apply(Employee employee) { return (employee != null && Gender.MALE.equals(employee.getGender())); } }
这是MinSalaryFilter类的代码:
package org.trishinfotech.filter.example2; import org.trishinfotech.filter.Employee; public class MinSalaryFilter implements Filter { private int minSalary; public MinSalaryFilter(int minSalary) { super(); this.minSalary = minSalary; } @Override public boolean apply(Employee employee) { return (employee != null && employee.getSalary() >= minSalary); } }
同样,这是forFilter类的:
package org.trishinfotech.filter.example2; import org.trishinfotech.filter.Employee; public class AndFilter implements Filter { private Filter filter; private Filter anotherFilter; public AndFilter(Filter filter, Filter anotherFilter) { this.filter = filter; this.anotherFilter = anotherFilter; } @Override public boolean apply(Employee employee) { boolean firstFilter = filter.apply(employee); boolean secondFilter = anotherFilter.apply(employee); return firstFilter && secondFilter; } }
package org.trishinfotech.filter.example2; import org.trishinfotech.filter.Employee; public class OrFilter implements Filter { private Filter filter; private Filter anotherFilter; public OrFilter(Filter Filter, Filter anotherFilter) { this.filter = Filter; this.anotherFilter = anotherFilter; } @Override public boolean apply(Employee employee) { boolean firstFilter = filter.apply(employee); boolean secondFilter = anotherFilter.apply(employee); return firstFilter || secondFilter; } }
更简单!是的,这是因为遍历集合已移至客户端应用程序(本例中为Main类)
现在,让我们编写Main 类来执行和测试输出:
package org.trishinfotech.filter.example2; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.trishinfotech.filter.Deptt; import org.trishinfotech.filter.Employee; import org.trishinfotech.filter.Gender; public class Main { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee.EmployeeBuilder().empNo(101).name("Brijesh").gender(Gender.MALE).depttName(Deptt.ENG) .salary(140000).projectName("Builder Pattern").build(), new Employee.EmployeeBuilder().empNo(102).name("Racheal").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(90000).projectName("Factory Pattern").build(), new Employee.EmployeeBuilder().empNo(103).name("Kim").gender(Gender.MALE).depttName(Deptt.HR) .salary(150000).projectName("Editorial").build(), new Employee.EmployeeBuilder().empNo(104).name("Micheal").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(80000).projectName("Decorator Pattern").build(), new Employee.EmployeeBuilder().empNo(105).name("Martin").gender(Gender.MALE).depttName(Deptt.SUPPORT) .salary(65000).projectName("Web Management").build(), new Employee.EmployeeBuilder().empNo(106).name("Pierce").gender(Gender.MALE).depttName(Deptt.HR) .salary(130000).projectName("Audit").build(), new Employee.EmployeeBuilder().empNo(107).name("Anjali").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(60000).projectName("State Pattern").build(), new Employee.EmployeeBuilder().empNo(108).name("Angelina").gender(Gender.FEMALE).depttName(Deptt.ENG) .salary(70000).projectName("Flyweight Pattern").build(), new Employee.EmployeeBuilder().empNo(109).name("Hemant").gender(Gender.MALE).depttName(Deptt.HR) .salary(170000).projectName("Audit").build(), new Employee.EmployeeBuilder().empNo(110).name("Mike").gender(Gender.MALE).depttName(Deptt.IT) .salary(150000).projectName("Networking").build()); System.out.println("Print all employees..."); printEmployees(employees); List<Employee> maleEmployees = applyFilter(new MaleFilter(), employees); System.out.println("Print all Male employees..."); printEmployees(maleEmployees); List<Employee> maleEngEmployees = applyFilter(new AndFilter(new MaleFilter(), new MinSalaryFilter(140000)), employees); System.out.println("Print all Male And Min Salary 140000 employees..."); printEmployees(maleEngEmployees); // now lets try the same with the help of Java Lambda Expressions... System.out.println("\n\n\nnow lets try the same with the help of Java Lambda Expressions..."); List<Employee> maleEmployeesUsingLambda = employees.stream() .filter(employee -> Gender.MALE.equals(employee.getGender())).collect(Collectors.toList()); System.out.println("Print all Male employees using lambda..."); printEmployees(maleEmployeesUsingLambda); List<Employee> maleEngEmployeesUsingLambda = employees.stream() .filter(employee -> Gender.MALE.equals(employee.getGender())) .filter(employee -> Deptt.ENG.equals(employee.getDepttName())).collect(Collectors.toList()); System.out.println("Print all Male And ENG employees using lambda..."); printEmployees(maleEngEmployeesUsingLambda); } private static List<Employee> applyFilter(Filter filter, List<Employee> employees) { return employees.stream().filter(employee -> filter.apply(employee)).collect(Collectors.toList()); } private static void printEmployees(List<Employee> employees) { System.out.println("======================================================================"); employees.stream().forEach(employee -> System.out.println(employee)); System.out.println("======================================================================"); } }
下面是输出:
Print all employees... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=102, name=Racheal, gender=FEMALE, depttName=ENG, salary=90000, mgrEmpNo=0, projectName=Factory Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=104, name=Micheal, gender=FEMALE, depttName=ENG, salary=80000, mgrEmpNo=0, projectName=Decorator Pattern] Employee [empNo=105, name=Martin, gender=MALE, depttName=SUPPORT, salary=65000, mgrEmpNo=0, projectName=Web Management] Employee [empNo=106, name=Pierce, gender=MALE, depttName=HR, salary=130000, mgrEmpNo=0, projectName=Audit Employee [empNo=107, name=Anjali, gender=FEMALE, depttName=ENG, salary=60000, mgrEmpNo=0, projectName=State Pattern] Employee [empNo=108, name=Angelina, gender=FEMALE, depttName=ENG, salary=70000, mgrEmpNo=0, projectName=Flyweight Pattern] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== Print all Male employees... ===================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=105, name=Martin, gender=MALE, depttName=SUPPORT, salary=65000, mgrEmpNo=0, projectName=Web Management] Employee [empNo=106, name=Pierce, gender=MALE, depttName=HR, salary=130000, mgrEmpNo=0, projectName=Audit] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== Print all Male And Min Salary 140000 employees... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== now lets try the same with the help of Java Lambda Expressions... Print all Male employees using lambda... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] Employee [empNo=103, name=Kim, gender=MALE, depttName=HR, salary=150000, mgrEmpNo=0, projectName=Editorial] Employee [empNo=105, name=Martin, gender=MALE, depttName=SUPPORT, salary=65000, mgrEmpNo=0, projectName=Web Management] Employee [empNo=106, name=Pierce, gender=MALE, depttName=HR, salary=130000, mgrEmpNo=0, projectName=Audit] Employee [empNo=109, name=Hemant, gender=MALE, depttName=HR, salary=170000, mgrEmpNo=0, projectName=Audit] Employee [empNo=110, name=Mike, gender=MALE, depttName=IT, salary=150000, mgrEmpNo=0, projectName=Networking] ====================================================================== Print all Male And ENG employees using lambda... ====================================================================== Employee [empNo=101, name=Brijesh, gender=MALE, depttName=ENG, salary=140000, mgrEmpNo=0, projectName=Builder Pattern] ======================================================================
你知道吗?通过使用Java 8或更高版本,我们甚至根本不需要定义过滤器,并且可以像在使用lambda时在Main中那样使用Java谓词 来创建过滤器条件。
好吧,这一切!我希望本教程有助于理解过滤器模式。
原文链接:http://codingdict.com