找回密码
 立即注册
首页 业界区 业界 【过滤器设计模式详解】C/Java/JS/Go/Python/TS不同语言 ...

【过滤器设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

笃扇 2025-6-6 09:40:44
简介

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern),是一种结构型模式。这种模式允许使用不同的标准条件来过滤一组对象,并通过逻辑运算的方式把各条件连接起来,它结合多个标准来获得单一标准。
例子将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。Test 类使用 Criteria 对象,基于各种标准和它们的结合来过滤 Person 对象的列表。
 
作用


  • 可以通过层层筛选,过滤出自己想要的结果。
  • 面向接口编程,将对象过滤,接口不依赖对象;对象无入侵,每次只需要增加规则就行了,不用修改过滤对象类。
 
实现步骤


  • 创建Criteria基础接口,定义过滤方法。
  • 创建多个条件类,实现过滤逻辑。
  • 客户端调用时,通条件类过滤数据。
 
UML

1.png

 
 
Java代码

 
标准接口类
  1. // Criteria.java 定义抽象标准接口,聚合实体对象
  2. public interface Criteria {
  3.    public List<Person> filter(List<Person> persons);
  4. }
复制代码
 
 
具体标准实现类

 
  1. // AndCriteria.java 定义And过滤标准
  2. public class AndCriteria implements Criteria {
  3.    private Criteria criteria;
  4.    private Criteria otherCriteria;
  5.    public AndCriteria(Criteria criteria, Criteria otherCriteria) {
  6.       this.criteria = criteria;
  7.       this.otherCriteria = otherCriteria;
  8.    }
  9.    @Override
  10.    public List<Person> filter(List<Person> persons) {
  11.       List<Person> firstCriteriaPersons = criteria.filter(persons);
  12.       return otherCriteria.filter(firstCriteriaPersons);
  13.    }
  14. }
  15. // OrCriteria.java 定义Or过滤标准
  16. public class OrCriteria implements Criteria {
  17.    private Criteria criteria;
  18.    private Criteria otherCriteria;
  19.    public OrCriteria(Criteria criteria, Criteria otherCriteria) {
  20.       this.criteria = criteria;
  21.       this.otherCriteria = otherCriteria;
  22.    }
  23.    @Override
  24.    public List<Person> filter(List<Person> persons) {
  25.       List<Person> firstCriteriaItems = criteria.filter(persons);
  26.       List<Person> otherCriteriaItems = otherCriteria.filter(persons);
  27.       for (Person person : otherCriteriaItems) {
  28.          if (!firstCriteriaItems.contains(person)) {
  29.             firstCriteriaItems.add(person);
  30.          }
  31.       }
  32.       return firstCriteriaItems;
  33.    }
  34. }
  35. // CriteriaFemale.java 根据标准接口实现的过滤
  36. public class CriteriaFemale implements Criteria {
  37.   @Override
  38.   public List<Person> filter(List<Person> persons) {
  39.     List<Person> femalePersons = new ArrayList<Person>();
  40.     for (Person person : persons) {
  41.       if (person.getGender().equalsIgnoreCase("FEMALE")) {
  42.         femalePersons.add(person);
  43.       }
  44.     }
  45.     return femalePersons;
  46.   }
  47. }
  48. // CriteriaMale.java 根据标准接口实现的过滤
  49. public class CriteriaMale implements Criteria {
  50.    @Override
  51.    public List<Person> filter(List<Person> persons) {
  52.       List<Person> malePersons = new ArrayList<Person>();
  53.       for (Person person : persons) {
  54.          if (person.getGender().equalsIgnoreCase("MALE")) {
  55.             malePersons.add(person);
  56.          }
  57.       }
  58.       return malePersons;
  59.    }
  60. }
  61. // CriteriaSingle.java 根据标准接口实现按属性的过滤
  62. public class CriteriaSingle implements Criteria {
  63.    @Override
  64.    public List<Person> filter(List<Person> persons) {
  65.       List<Person> singlePersons = new ArrayList<Person>();
  66.       for (Person person : persons) {
  67.          if (person.getStatus().equalsIgnoreCase("SINGLE")) {
  68.             singlePersons.add(person);
  69.          }
  70.       }
  71.       return singlePersons;
  72.    }
  73. }
复制代码
 
业务实体类

 
  1. // Person.java 定义一个实体类,用来过滤的对象
  2. public class Person {
  3.    private String name;
  4.    private String gender;
  5.    private String status;
  6.    public Person(String name, String gender, String status) {
  7.       this.name = name;
  8.       this.gender = gender;
  9.       this.status = status;
  10.    }
  11.    public String getName() {
  12.       return name;
  13.    }
  14.    public String getGender() {
  15.       return gender;
  16.    }
  17.    public String getStatus() {
  18.       return status;
  19.    }
  20.    public String toString() {
  21.       return "Person : [ Name : " + getName() + ", Gender : "
  22.             + getGender() + ", Marital Status : " + getStatus() + " ]";
  23.    }
  24. }
复制代码
 
测试调用

 
  1.     /**
  2.      * 过滤器模式就是不断组合过滤条件,然后层层过滤的模式
  3.      * 这里是简单演示,用List筛选来模拟过滤,实际例子有各种数据结构
  4.      */
  5.     List<Person> persons = new ArrayList<Person>();
  6.     persons.add(new Person("王男单", "Male", "Single"));
  7.     persons.add(new Person("李男婚", "Male", "Married"));
  8.     persons.add(new Person("张女婚", "Female", "Married"));
  9.     persons.add(new Person("赵女单", "Female", "Single"));
  10.     persons.add(new Person("刘男单", "Male", "Single"));
  11.     persons.add(new Person("杨男单", "Male", "Single"));
  12.     Criteria male = new CriteriaMale();
  13.     Criteria female = new CriteriaFemale();
  14.     Criteria single = new CriteriaSingle();
  15.     Criteria singleMale = new AndCriteria(single, male);
  16.     Criteria singleOrFemale = new OrCriteria(single, female);
  17.     // 查询男性
  18.     System.out.println("Males: ");
  19.     printPersons(male.filter(persons));
  20.     // 查询女性
  21.     System.out.println("\nFemales: ");
  22.     printPersons(female.filter(persons));
  23.     // 嵌套查询女性且单身
  24.     System.out.println("\nFemales and Single: ");
  25.     printPersons(single.filter(female.filter(persons)));
  26.     // 查询男性男性单身
  27.     System.out.println("\nSingle Males: ");
  28.     printPersons(singleMale.filter(persons));
  29.     // 查询女性或单身
  30.     System.out.println("\nSingle Or Females: ");
  31.     printPersons(singleOrFemale.filter(persons));
复制代码
 
C代码

 
head文件

 
  1. // func.h文件
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7. char *str_toupper(char str[]);
  8. char *str_tolower(char str[]);
  9. // 定义用于过滤的Person数组查询对象
  10. // 因C语言无法定义动态数组,将数组长度存在此处
  11. typedef struct FilterPersons
  12. {
  13.     int length;
  14.     struct Person **persons;
  15. } FilterPersons;
  16. // 定义一个实体类,用来过滤的对象
  17. typedef struct Person
  18. {
  19.     char name[50];
  20.     char gender[20];
  21.     char status[20];
  22.     char *(*get_name)(struct Person *);
  23.     char *(*to_string)(struct Person *);
  24.     bool (*is_contained)(struct Person *, struct FilterPersons *);
  25. } Person;
  26. Person *person_constructor(char *name, char *gender, char *status);
  27. // 定义抽象标准接口,聚合要过滤的对象集合
  28. typedef struct Criteria
  29. {
  30.     struct Criteria *first_criteria;
  31.     struct Criteria *other_criteria;
  32.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  33. } Criteria;
  34. // 根据标准接口实现的过滤
  35. typedef struct CriteriaFemale
  36. {
  37.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  38. } CriteriaFemale;
  39. CriteriaFemale *criteria_female_constructor();
  40. // 根据标准接口实现的过滤
  41. typedef struct CriteriaMale
  42. {
  43.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  44. } CriteriaMale;
  45. CriteriaMale *criteria_male_constructor();
  46. // 根据标准接口实现的过滤
  47. typedef struct CriteriaSingle
  48. {
  49.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  50. } CriteriaSingle;
  51. CriteriaSingle *criteria_single_constructor();
  52. // 定义And过滤标准
  53. typedef struct AndCriteria
  54. {
  55.     struct Criteria *first_criteria;
  56.     struct Criteria *other_criteria;
  57.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  58. } AndCriteria;
  59. AndCriteria *and_criteria_constructor(Criteria *, Criteria *);
  60. // 定义Or过滤标准
  61. typedef struct OrCriteria
  62. {
  63.     struct Criteria *first_criteria;
  64.     struct Criteria *other_criteria;
  65.     FilterPersons *(*filter)(FilterPersons *, struct Criteria *);
  66. } OrCriteria;
  67. OrCriteria *or_criteria_constructor(Criteria *, Criteria *);
复制代码
 
条件接口类

 
  1. // criteria.c 定义抽象标准接口,聚合实体对象
  2. #include "func.h"
  3. // c语言没有抽象类或接口,Criterial作为基础struct定义在head, 这里放一些公共函数
  4. char *str_toupper(char str[])
  5. {
  6.     int size = strlen(str);
  7.     char *result = (char *)malloc(size * sizeof(char));
  8.     int i = 0;
  9.     while (str[i])
  10.     {
  11.         result[i] = toupper(str[i]);
  12.         i++;
  13.     }
  14.     return result;
  15. }
  16. char *str_tolower(char str[])
  17. {
  18.     int size = strlen(str);
  19.     char *result = (char *)malloc(size * sizeof(char));
  20.     int i = 0;
  21.     while (str[i])
  22.     {
  23.         result[i] = tolower(str[i]);
  24.         i++;
  25.     }
  26.     return result;
  27. }
复制代码
 
 
具体标准实现类

 
  1. // and_criteria.c 定义And过滤标准
  2. #include "func.h"
  3. // 先过滤条件1,再把结果按照条件2进行过滤
  4. FilterPersons *and_criteria_filter(FilterPersons *filter, Criteria *criteria)
  5. {
  6.   FilterPersons *first_filter = criteria->first_criteria->filter(filter, criteria);
  7.   return criteria->other_criteria->filter(first_filter, criteria);
  8. }
  9. AndCriteria *and_criteria_constructor(Criteria *first_criteria, Criteria *other_criteria)
  10. {
  11.   Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  12.   criteria->filter = &and_criteria_filter;
  13.   AndCriteria *and_criteria = (AndCriteria *)criteria;
  14.   and_criteria->first_criteria = first_criteria;
  15.   and_criteria->other_criteria = other_criteria;
  16.   and_criteria->filter = &and_criteria_filter;
  17.   return and_criteria;
  18. }
  19. // or_criteria.c 定义Or过滤标准
  20. #include "func.h"
  21. // 先过滤条件1,再把结果按照条件2进行过滤
  22. FilterPersons *or_criteria_filter(FilterPersons *filter, Criteria *criteria)
  23. {
  24.   FilterPersons *first_filter = criteria->first_criteria->filter(filter, criteria);
  25.   FilterPersons *other_filter = criteria->other_criteria->filter(filter, criteria);
  26.   int first_size = first_filter->length;
  27.   int other_size = other_filter->length;
  28.   for (int i = 0; i < other_size; i++)
  29.   {
  30.     Person *person = other_filter->persons[i];
  31.     // 符合项如果不存在条件1里,则追加到条件1里去
  32.     if (!person->is_contained(person, first_filter))
  33.     {
  34.       // 这里数组长度直接增加
  35.       first_filter->persons[first_size++] = person;
  36.     }
  37.   }
  38.   first_filter->length = first_size;
  39.   return first_filter;
  40. }
  41. OrCriteria *or_criteria_constructor(Criteria *first_criteria, Criteria *other_criteria)
  42. {
  43.   Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  44.   criteria->filter = &or_criteria_filter;
  45.   OrCriteria *or_criteria = (OrCriteria *)criteria;
  46.   or_criteria->first_criteria = first_criteria;
  47.   or_criteria->other_criteria = other_criteria;
  48.   or_criteria->filter = &or_criteria_filter;
  49.   return or_criteria;
  50. }
  51. // ccriteria_female.c 根据标准接口实现的过滤
  52. #include "func.h"
  53. // 根据是否女性进行过滤
  54. FilterPersons *criteria_female_filter(FilterPersons *filter, Criteria *criteria)
  55. {
  56.   int person_size = filter->length;
  57.   int *female_index_list = (int *)malloc(person_size * sizeof(int));
  58.   int count = 0;
  59.   char *gender;
  60.   for (int i = 0; i < person_size; i++)
  61.   {
  62.     if (filter->persons[i] == NULL)
  63.     {
  64.       break;
  65.     }
  66.     gender = str_toupper(filter->persons[i]->gender);
  67.     if (strcmp(gender, "FEMALE") == 0)
  68.     {
  69.       // 记录下所有符合条件的person下标
  70.       female_index_list[count] = i;
  71.       count += 1;
  72.     }
  73.   }
  74.   free(gender);
  75.   free(female_index_list);
  76.   // 将符合条件的person追加到新数组
  77.   Person **female_persons = (Person **)calloc(count, sizeof(Person));
  78.   for (int i = 0; i < count; i++)
  79.   {
  80.     female_persons[i] = filter->persons[female_index_list[i]];
  81.   }
  82.   FilterPersons *female_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  83.   female_filter->length = count;
  84.   female_filter->persons = female_persons;
  85.   return female_filter;
  86. }
  87. CriteriaFemale *criteria_female_constructor()
  88. {
  89.   Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  90.   criteria->filter = &criteria_female_filter;
  91.   CriteriaFemale *criteria_female = (CriteriaFemale *)criteria;
  92.   criteria_female->filter = &criteria_female_filter;
  93.   return criteria_female;
  94. }
  95. // criteria_male.c 根据标准接口实现的过滤
  96. #include "func.h"
  97. // 根据是否男性进行过滤
  98. FilterPersons *criteria_male_filter(FilterPersons *filter, Criteria *criteria)
  99. {
  100.   int person_size = filter->length;
  101.   int *male_index_list = (int *)malloc(person_size * sizeof(int));
  102.   int count = 0;
  103.   char *gender;
  104.   for (int i = 0; i < person_size; i++)
  105.   {
  106.     if (filter->persons[i] == NULL)
  107.     {
  108.       break;
  109.     }
  110.     gender = str_tolower(filter->persons[i]->gender);
  111.     if (strcmp(gender, "male") == 0)
  112.     {
  113.       // 记录下所有符合条件的person下标
  114.       male_index_list[count] = i;
  115.       count += 1;
  116.     }
  117.   }
  118.   free(gender);
  119.   free(male_index_list);
  120.   // 将符合条件的person追加到新数组
  121.   Person **male_persons = (Person **)calloc(count, sizeof(Person));
  122.   for (int i = 0; i < count; i++)
  123.   {
  124.     male_persons[i] = filter->persons[male_index_list[i]];
  125.   }
  126.   FilterPersons *male_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  127.   male_filter->length = count;
  128.   male_filter->persons = male_persons;
  129.   return male_filter;
  130. }
  131. CriteriaMale *criteria_male_constructor()
  132. {
  133.   Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  134.   criteria->filter = &criteria_male_filter;
  135.   CriteriaMale *criteria_male = (CriteriaMale *)criteria;
  136.   criteria_male->filter = &criteria_male_filter;
  137.   return criteria_male;
  138. }
  139. // criteria_single.c 根据标准接口实现按属性的过滤
  140. #include "func.h"
  141. // 根据是否单身进行过滤
  142. FilterPersons *criteria_single_filter(FilterPersons *filter, Criteria *criteria)
  143. {
  144.   int person_size = filter->length;
  145.   int *single_index_list = (int *)malloc(person_size * sizeof(int));
  146.   int count = 0;
  147.   char *status;
  148.   for (int i = 0; i < person_size; i++)
  149.   {
  150.     if (filter->persons[i] == NULL)
  151.     {
  152.       break;
  153.     }
  154.     status = str_tolower(filter->persons[i]->status);
  155.     if (strcmp(status, "single") == 0)
  156.     {
  157.       // 记录下所有符合条件的person下标
  158.       single_index_list[count] = i;
  159.       count += 1;
  160.     }
  161.   }
  162.   free(status);
  163.   free(single_index_list);
  164.   // 将符合条件的person追加到新数组
  165.   Person **single_persons = (Person **)calloc(count, sizeof(Person));
  166.   for (int i = 0; i < count; i++)
  167.   {
  168.     single_persons[i] = filter->persons[single_index_list[i]];
  169.   }
  170.   FilterPersons *single_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  171.   single_filter->length = count;
  172.   single_filter->persons = single_persons;
  173.   return single_filter;
  174. }
  175. CriteriaSingle *criteria_single_constructor()
  176. {
  177.   Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  178.   criteria->filter = &criteria_single_filter;
  179.   CriteriaSingle *criteria_single = (CriteriaSingle *)criteria;
  180.   criteria_single->filter = &criteria_single_filter;
  181.   return criteria_single;
  182. }
复制代码
 
 
业务实体类

 
  1. // person.c 定义一个实体类,用来过滤的对象
  2. #include "func.h"
  3. // 是否被包含在对象数组中
  4. bool person_is_contained(Person *person, FilterPersons *filter)
  5. {
  6.   int persons_size = filter->length;
  7.   for (int i = 0; i < persons_size; i++)
  8.   {
  9.     if (filter->persons[i] == person)
  10.     {
  11.       return true;
  12.     }
  13.   }
  14.   return false;
  15. }
  16. char *person_get_name(Person *person)
  17. {
  18.   return person->name;
  19. }
  20. // 返回字符串
  21. char *person_to_string(Person *person)
  22. {
  23.   char *result = (char *)malloc(500 * sizeof(char));
  24.   strcat(result, "Person :[ name :");
  25.   strcat(result, person->name);
  26.   strcat(result, ", gender : ");
  27.   strcat(result, person->gender);
  28.   strcat(result, ", status : ");
  29.   strcat(result, person->status);
  30.   strcat(result, "]");
  31.   return result;
  32. }
  33. Person *person_constructor(char *name, char *gender, char *status)
  34. {
  35.   Person *person = (Person *)malloc(sizeof(Person));
  36.   strncpy(person->name, name, 50);
  37.   strncpy(person->gender, gender, 20);
  38.   strncpy(person->status, status, 20);
  39.   person->get_name = &person_get_name;
  40.   person->to_string = &person_to_string;
  41.   person->is_contained = &person_is_contained;
  42.   return person;
  43. }
复制代码
 
测试调用
  1.     /**
  2.      * 过滤器模式就是不断组合过滤条件,然后层层过滤的模式
  3.      * 这里是简单演示,用List筛选来模拟过滤,实际例子有各种数据结构。
  4.      */
  5.     int data_size = 6;
  6.     // 定义一些数据
  7.     char data[6][3][100] = {
  8.         {"王男单", "Male", "Single"},
  9.         {"李男婚", "Male", "Married"},
  10.         {"张女婚", "Female", "Married"},
  11.         {"赵女单", "Female", "Single"},
  12.         {"刘男单", "Male", "Single"},
  13.         {"杨男单", "Male", "Single"}};
  14.     // 定义persons数组
  15.     Person *persons[data_size];
  16.     for (int i = 0; i < data_size; i++)
  17.     {
  18.         char *name = data[i][0];
  19.         char *gender = data[i][1];
  20.         char *status = data[i][2];
  21.         Person *person = person_constructor(name, gender, status);
  22.         persons[i] = person;
  23.     }
  24.     // 构建查询对象
  25.     FilterPersons *filter_persons = (FilterPersons *)malloc(sizeof(FilterPersons *));
  26.     filter_persons->length = data_size;
  27.     filter_persons->persons = persons;
  28.     // 声明属性过滤条件,可用Criteria或具体条件声明
  29.     Criteria *criteria_male = (Criteria *)criteria_male_constructor();
  30.     CriteriaFemale *criteria_female = criteria_female_constructor();
  31.     Criteria *criteria_single = (Criteria *)criteria_single_constructor();
  32.     // 声明逻辑条件,传入属性过滤条件
  33.     Criteria *single_male = (Criteria *)and_criteria_constructor(criteria_single, criteria_male);
  34.     OrCriteria *single_or_female = or_criteria_constructor(criteria_single, (Criteria *)criteria_female);
  35.     // 查询男性
  36.     printf("\n Males: ");
  37.     print_persons(((CriteriaMale *)criteria_male)->filter(filter_persons, criteria_male));
  38.     // 查询女性
  39.     printf("\nFemales: ");
  40.     print_persons(criteria_female->filter(filter_persons, (Criteria *)criteria_female));
  41.     // 嵌套查询女性且单身
  42.     printf("\nFemales and Single: ");
  43.     FilterPersons *females = criteria_female->filter(filter_persons, (Criteria *)criteria_female);
  44.     print_persons(((CriteriaSingle *)criteria_single)->filter(females, criteria_single));
  45.     // 查询男性男性单身
  46.     printf("\nSingle Males: ");
  47.     // 逐个条件过滤,与下面AndCriteria效果相同
  48.     FilterPersons *single_males = ((CriteriaMale *)criteria_male)->filter(filter_persons, criteria_male);
  49.     print_persons(((CriteriaSingle *)criteria_single)->filter(single_males, criteria_single));
  50.     printf("\nSingle Males: ");
  51.     // 通过AndCriteria来过滤
  52.     FilterPersons *single_males2 = ((AndCriteria *)single_male)->filter(filter_persons, single_male);
  53.     print_persons(single_males2);
  54.     // 查询女性或单身
  55.     printf("\nSingle Or Females: ");
  56.     print_persons(single_or_female->filter(filter_persons, (Criteria *)single_or_female));
  57.     free(filter_persons);
  58.     free(criteria_male);
  59.     free(criteria_female);
  60.     free(criteria_single);
  61.     free(single_male);
  62.     free(single_or_female);
  63.     return 0;
复制代码
 
 
更多语言版本

不同语言实现设计模式:https://github.com/microwind/design-pattern

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册