当前位置:   article > 正文

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

python设计模式过滤器模式

简介

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern),是一种结构型模式。这种模式允许使用不同的标准条件来过滤一组对象,并通过逻辑运算的方式把各条件连接起来,它结合多个标准来获得单一标准。

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

作用

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

实现步骤

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

UML

 

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. }

  1. // OrCriteria.java 定义Or过滤标准
  2. public class OrCriteria implements Criteria {
  3. private Criteria criteria;
  4. private Criteria otherCriteria;
  5. public OrCriteria(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> firstCriteriaItems = criteria.filter(persons);
  12. List<Person> otherCriteriaItems = otherCriteria.filter(persons);
  13. for (Person person : otherCriteriaItems) {
  14. if (!firstCriteriaItems.contains(person)) {
  15. firstCriteriaItems.add(person);
  16. }
  17. }
  18. return firstCriteriaItems;
  19. }
  20. }

  1. // CriteriaFemale.java 根据标准接口实现的过滤
  2. public class CriteriaFemale implements Criteria {
  3. @Override
  4. public List<Person> filter(List<Person> persons) {
  5. List<Person> femalePersons = new ArrayList<Person>();
  6. for (Person person : persons) {
  7. if (person.getGender().equalsIgnoreCase("FEMALE")) {
  8. femalePersons.add(person);
  9. }
  10. }
  11. return femalePersons;
  12. }
  13. }

  1. // CriteriaMale.java 根据标准接口实现的过滤
  2. public class CriteriaMale implements Criteria {
  3. @Override
  4. public List<Person> filter(List<Person> persons) {
  5. List<Person> malePersons = new ArrayList<Person>();
  6. for (Person person : persons) {
  7. if (person.getGender().equalsIgnoreCase("MALE")) {
  8. malePersons.add(person);
  9. }
  10. }
  11. return malePersons;
  12. }
  13. }

  1. // CriteriaSingle.java 根据标准接口实现按属性的过滤
  2. public class CriteriaSingle implements Criteria {
  3. @Override
  4. public List<Person> filter(List<Person> persons) {
  5. List<Person> singlePersons = new ArrayList<Person>();
  6. for (Person person : persons) {
  7. if (person.getStatus().equalsIgnoreCase("SINGLE")) {
  8. singlePersons.add(person);
  9. }
  10. }
  11. return singlePersons;
  12. }
  13. }

业务实体类

  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. }

  1. // or_criteria.c 定义Or过滤标准
  2. #include "func.h"
  3. // 先过滤条件1,再把结果按照条件2进行过滤
  4. FilterPersons *or_criteria_filter(FilterPersons *filter, Criteria *criteria)
  5. {
  6. FilterPersons *first_filter = criteria->first_criteria->filter(filter, criteria);
  7. FilterPersons *other_filter = criteria->other_criteria->filter(filter, criteria);
  8. int first_size = first_filter->length;
  9. int other_size = other_filter->length;
  10. for (int i = 0; i < other_size; i++)
  11. {
  12. Person *person = other_filter->persons[i];
  13. // 符合项如果不存在条件1里,则追加到条件1里去
  14. if (!person->is_contained(person, first_filter))
  15. {
  16. // 这里数组长度直接增加
  17. first_filter->persons[first_size++] = person;
  18. }
  19. }
  20. first_filter->length = first_size;
  21. return first_filter;
  22. }
  23. OrCriteria *or_criteria_constructor(Criteria *first_criteria, Criteria *other_criteria)
  24. {
  25. Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  26. criteria->filter = &or_criteria_filter;
  27. OrCriteria *or_criteria = (OrCriteria *)criteria;
  28. or_criteria->first_criteria = first_criteria;
  29. or_criteria->other_criteria = other_criteria;
  30. or_criteria->filter = &or_criteria_filter;
  31. return or_criteria;
  32. }

  1. // ccriteria_female.c 根据标准接口实现的过滤
  2. #include "func.h"
  3. // 根据是否女性进行过滤
  4. FilterPersons *criteria_female_filter(FilterPersons *filter, Criteria *criteria)
  5. {
  6. int person_size = filter->length;
  7. int *female_index_list = (int *)malloc(person_size * sizeof(int));
  8. int count = 0;
  9. char *gender;
  10. for (int i = 0; i < person_size; i++)
  11. {
  12. if (filter->persons[i] == NULL)
  13. {
  14. break;
  15. }
  16. gender = str_toupper(filter->persons[i]->gender);
  17. if (strcmp(gender, "FEMALE") == 0)
  18. {
  19. // 记录下所有符合条件的person下标
  20. female_index_list[count] = i;
  21. count += 1;
  22. }
  23. }
  24. free(gender);
  25. free(female_index_list);
  26. // 将符合条件的person追加到新数组
  27. Person **female_persons = (Person **)calloc(count, sizeof(Person));
  28. for (int i = 0; i < count; i++)
  29. {
  30. female_persons[i] = filter->persons[female_index_list[i]];
  31. }
  32. FilterPersons *female_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  33. female_filter->length = count;
  34. female_filter->persons = female_persons;
  35. return female_filter;
  36. }
  37. CriteriaFemale *criteria_female_constructor()
  38. {
  39. Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  40. criteria->filter = &criteria_female_filter;
  41. CriteriaFemale *criteria_female = (CriteriaFemale *)criteria;
  42. criteria_female->filter = &criteria_female_filter;
  43. return criteria_female;
  44. }

  1. // criteria_male.c 根据标准接口实现的过滤
  2. #include "func.h"
  3. // 根据是否男性进行过滤
  4. FilterPersons *criteria_male_filter(FilterPersons *filter, Criteria *criteria)
  5. {
  6. int person_size = filter->length;
  7. int *male_index_list = (int *)malloc(person_size * sizeof(int));
  8. int count = 0;
  9. char *gender;
  10. for (int i = 0; i < person_size; i++)
  11. {
  12. if (filter->persons[i] == NULL)
  13. {
  14. break;
  15. }
  16. gender = str_tolower(filter->persons[i]->gender);
  17. if (strcmp(gender, "male") == 0)
  18. {
  19. // 记录下所有符合条件的person下标
  20. male_index_list[count] = i;
  21. count += 1;
  22. }
  23. }
  24. free(gender);
  25. free(male_index_list);
  26. // 将符合条件的person追加到新数组
  27. Person **male_persons = (Person **)calloc(count, sizeof(Person));
  28. for (int i = 0; i < count; i++)
  29. {
  30. male_persons[i] = filter->persons[male_index_list[i]];
  31. }
  32. FilterPersons *male_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  33. male_filter->length = count;
  34. male_filter->persons = male_persons;
  35. return male_filter;
  36. }
  37. CriteriaMale *criteria_male_constructor()
  38. {
  39. Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  40. criteria->filter = &criteria_male_filter;
  41. CriteriaMale *criteria_male = (CriteriaMale *)criteria;
  42. criteria_male->filter = &criteria_male_filter;
  43. return criteria_male;
  44. }

  1. // criteria_single.c 根据标准接口实现按属性的过滤
  2. #include "func.h"
  3. // 根据是否单身进行过滤
  4. FilterPersons *criteria_single_filter(FilterPersons *filter, Criteria *criteria)
  5. {
  6. int person_size = filter->length;
  7. int *single_index_list = (int *)malloc(person_size * sizeof(int));
  8. int count = 0;
  9. char *status;
  10. for (int i = 0; i < person_size; i++)
  11. {
  12. if (filter->persons[i] == NULL)
  13. {
  14. break;
  15. }
  16. status = str_tolower(filter->persons[i]->status);
  17. if (strcmp(status, "single") == 0)
  18. {
  19. // 记录下所有符合条件的person下标
  20. single_index_list[count] = i;
  21. count += 1;
  22. }
  23. }
  24. free(status);
  25. free(single_index_list);
  26. // 将符合条件的person追加到新数组
  27. Person **single_persons = (Person **)calloc(count, sizeof(Person));
  28. for (int i = 0; i < count; i++)
  29. {
  30. single_persons[i] = filter->persons[single_index_list[i]];
  31. }
  32. FilterPersons *single_filter = (FilterPersons *)calloc(1, sizeof(FilterPersons));
  33. single_filter->length = count;
  34. single_filter->persons = single_persons;
  35. return single_filter;
  36. }
  37. CriteriaSingle *criteria_single_constructor()
  38. {
  39. Criteria *criteria = (Criteria *)malloc(sizeof(Criteria));
  40. criteria->filter = &criteria_single_filter;
  41. CriteriaSingle *criteria_single = (CriteriaSingle *)criteria;
  42. criteria_single->filter = &criteria_single_filter;
  43. return criteria_single;
  44. }

业务实体类

  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;

更多语言版本

不同语言实现设计模式,敬请关注:GitHub - microwind/design-pattern: Design Pattern 经典设计模式 C/Java/Go/JavaScript/Python等不同语言详解 FP/OOP/MVC/MVP/MVVM/DDD等设计思想研究

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/482051
推荐阅读
相关标签
  

闽ICP备14008679号