过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。我们的演示类使用 Criteria 对象,基于各种标准和它们的结合来过滤 Person 对象的列表。

简单的对象的创建

这里写了一些简单的额POJO对象,用于演示使用,主要就是Person和枚举类型.

  • @Data 是Lombok提供的插件支持,没有的话,可以手写setter/getter方法

Person

  1. import lombok.Data;
  2. import lombok.ToString;
  3. import lombok.experimental.Accessors;
  4. @Data
  5. @Accessors(chain = true)
  6. @ToString
  7. public class Person {
  8. private String name;
  9. private String gender;
  10. private int age;
  11. public Person(String name, String gender, int age) {
  12. this.name = name;
  13. this.gender = gender;
  14. this.age = age;
  15. }
  16. }

GenderStatus

性别状态信息

  1. /**
  2. * 作用:
  3. *
  4. * <p>时间:2018/6/26 22:08
  5. *
  6. * <p>位置:com.tao.example.design.criteria.entity
  7. *
  8. * @author Yan - tao - zhoutao825638@vip.qq.com
  9. */
  10. public enum GenderStatus {
  11. FEMALE,
  12. MALE
  13. }

过滤器的实现

过滤器接口

  1. public interface Criteria {
  2. /**
  3. * 过滤器
  4. *
  5. * @param persons
  6. * @return
  7. */
  8. List<Person> meetCriteria(List<Person> persons);
  9. }

基本过滤器

男性过滤器

  1. public class CriteriaMale implements Criteria {
  2. @Override
  3. public List<Person> meetCriteria(List<Person> persons) {
  4. List<Person> collect =
  5. persons
  6. .stream()
  7. .filter(
  8. person -> {
  9. return person.getGender().equals(GenderStatus.MALE.name());
  10. })
  11. .collect(Collectors.toList());
  12. return collect;
  13. }
  14. }

女性过滤器

  1. public class CriteriaFemale implements Criteria {
  2. @Override
  3. public List<Person> meetCriteria(List<Person> persons) {
  4. List<Person> collect =
  5. persons
  6. .stream()
  7. .filter(
  8. person -> {
  9. return person.getGender().equals(GenderStatus.FEMALE.name());
  10. })
  11. .collect(Collectors.toList());
  12. return collect;
  13. }
  14. }

成年过滤器

  1. public class CriteriaAdult implements Criteria {
  2. @Override
  3. public List<Person> meetCriteria(List<Person> persons) {
  4. List<Person> personList =
  5. persons.stream().filter(person -> person.getAge() >= 18).collect(Collectors.toList());
  6. return personList;
  7. }
  8. }

逻辑过滤器组合

交集过滤器

提供两个基本过滤器,采用与操作线性过滤

  1. public class AndCriteria implements Criteria {
  2. private Criteria mainCriteria;
  3. private Criteria otherCriteria;
  4. public AndCriteria(Criteria mainCriteria, Criteria otherCriteria) {
  5. this.mainCriteria = mainCriteria;
  6. this.otherCriteria = otherCriteria;
  7. }
  8. @Override
  9. public List<Person> meetCriteria(List<Person> persons) {
  10. List<Person> mainCriteriaPersons = mainCriteria.meetCriteria(persons);
  11. List<Person> personList = otherCriteria.meetCriteria(mainCriteriaPersons);
  12. return personList;
  13. }
  14. }

并集过滤器

原理和交集过滤器类似

  1. public class OrCriteria implements Criteria {
  2. private Criteria mainCriteria;
  3. private Criteria otherCriteria;
  4. public OrCriteria(Criteria mainCriteria, Criteria otherCriteria) {
  5. this.mainCriteria = mainCriteria;
  6. this.otherCriteria = otherCriteria;
  7. }
  8. @Override
  9. public List<Person> meetCriteria(List<Person> persons) {
  10. List<Person> mainCriteriaPersons = mainCriteria.meetCriteria(persons);
  11. List<Person> otherCriteriaPersons = otherCriteria.meetCriteria(persons);
  12. mainCriteriaPersons.forEach(
  13. person -> {
  14. if (!otherCriteriaPersons.contains(mainCriteriaPersons)) {
  15. otherCriteriaPersons.add(person);
  16. }
  17. });
  18. return otherCriteriaPersons;
  19. }
  20. }

过滤效果测试

测试代码

使用如下代码测试

  1. public class TestCriteriaPattern {
  2. public static void main(String[] args) {
  3. List<Person> persons = new ArrayList<Person>();
  4. persons.add(new Person("赵清雅", GenderStatus.FEMALE.name(), 15));
  5. persons.add(new Person("李建岺", GenderStatus.MALE.name(), 16));
  6. persons.add(new Person("冯蕙茞", GenderStatus.FEMALE.name(), 17));
  7. persons.add(new Person("周踵武", GenderStatus.MALE.name(), 18));
  8. persons.add(new Person("杨畹兮", GenderStatus.FEMALE.name(), 15));
  9. persons.add(new Person("姜驰骛", GenderStatus.MALE.name(), 21));
  10. // 创建过滤器
  11. CriteriaFemale criteriaFemale = new CriteriaFemale();
  12. CriteriaMale criteriaMale = new CriteriaMale();
  13. CriteriaAdult criteriaAdult = new CriteriaAdult();
  14. AndCriteria maleAndAdult = new AndCriteria(criteriaMale, criteriaAdult);
  15. AndCriteria femaleAndAdult = new AndCriteria(criteriaFemale, criteriaAdult);
  16. OrCriteria femaleOrAdult = new OrCriteria(criteriaFemale, criteriaAdult);
  17. printPersons("男性过滤器", criteriaMale.meetCriteria(persons));
  18. printPersons("女性过滤器", criteriaFemale.meetCriteria(persons));
  19. printPersons("成年过滤器", criteriaAdult.meetCriteria(persons));
  20. printPersons("成年男性过滤器", maleAndAdult.meetCriteria(persons));
  21. printPersons("成年女过滤器", femaleAndAdult.meetCriteria(persons));
  22. printPersons("女性或成年过滤器", femaleOrAdult.meetCriteria(persons));
  23. }
  24. public static void printPersons(String criteriaName, List<Person> personList) {
  25. System.out.println(criteriaName);
  26. if (personList.size() == 0){
  27. System.out.println("\t 没有找到");
  28. }
  29. personList.forEach(
  30. person -> {
  31. System.out.println("\t" + person);
  32. });
  33. System.out.println("---------------------");
  34. }
  35. }

测试输出

  1. 男性过滤器
  2. Person(name=李建岺, gender=MALE, age=16)
  3. Person(name=周踵武, gender=MALE, age=18)
  4. Person(name=姜驰骛, gender=MALE, age=21)
  5. ---------------------
  6. 女性过滤器
  7. Person(name=赵清雅, gender=FEMALE, age=15)
  8. Person(name=冯蕙茞, gender=FEMALE, age=17)
  9. Person(name=杨畹兮, gender=FEMALE, age=15)
  10. ---------------------
  11. 成年过滤器
  12. Person(name=周踵武, gender=MALE, age=18)
  13. Person(name=姜驰骛, gender=MALE, age=21)
  14. ---------------------
  15. 成年男性过滤器
  16. Person(name=周踵武, gender=MALE, age=18)
  17. Person(name=姜驰骛, gender=MALE, age=21)
  18. ---------------------
  19. 成年女过滤器
  20. 没有找到
  21. ---------------------
  22. 女性或成年过滤器
  23. Person(name=周踵武, gender=MALE, age=18)
  24. Person(name=姜驰骛, gender=MALE, age=21)
  25. Person(name=赵清雅, gender=FEMALE, age=15)
  26. Person(name=冯蕙茞, gender=FEMALE, age=17)
  27. Person(name=杨畹兮, gender=FEMALE, age=15)
  28. ---------------------