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

意图

对同一组对象能够以不同过滤条件筛选出来

主要解决

能够以不同条件或条件的组合筛选对象

何时使用

一组对象需要根据属性作筛选时

如何解决

使用过滤器类进行筛选

应用实例

  1. 对用户信息根据不同条件如性别、婚姻状况筛选
  2. 对车辆根据根据不同条件如颜色、款式筛选

优点

能使用不同过滤器的组合方便的筛选对象

缺点

过滤器依赖对象的结构,对象属性变化时过滤器也需要变化,如示例中的婚姻状况增加了一种”离异”,则需要增加或修改过滤器

注意事项

过滤器应该尽量简单,复杂的过滤器应使用多个简单过滤器组合得到,这样当对象属性变化时,过滤器的改动能尽量小

示例

整理用户信息时,使用过滤器方便的筛选不同条件的人,比如筛选男性、女性、单身女性等等
image.png

  1. #include "pch.h"
  2. #include <iostream>
  3. #include <sstream>
  4. #include <vector>
  5. #include <algorithm>
  6. // 人
  7. class Person
  8. {
  9. public:
  10. Person(int ID, std::string name, std::string gender, std::string maritalStatus)
  11. {
  12. if ("Male" != gender && "Female" != gender) { throw "Invalid Parameter"; }
  13. if ("Single" != maritalStatus && "Married" != maritalStatus) { throw "Invalid Parameter"; }
  14. this->ID = ID;
  15. this->name = name;
  16. this->gender = gender;
  17. this->maritalStatus = maritalStatus;
  18. }
  19. std::string GetName()
  20. {
  21. return this->name;
  22. }
  23. std::string GetGender()
  24. {
  25. return this->gender;
  26. }
  27. std::string GetMaritalStatus()
  28. {
  29. return this->maritalStatus;
  30. }
  31. std::string Info()
  32. {
  33. std::string info;
  34. std::ostringstream ostr;
  35. ostr << "Person : [Name : " << name << ", Gender : " << gender << ", Marital Status : " << maritalStatus << "]";
  36. return ostr.str();
  37. }
  38. bool operator == (const Person & person) const
  39. {
  40. return this->ID == person.ID;
  41. }
  42. bool operator < (const Person & person) const
  43. {
  44. return this->ID < person.ID;
  45. }
  46. private:
  47. int ID;
  48. std::string name;
  49. std::string gender;
  50. std::string maritalStatus;
  51. };
  52. class ICriteria
  53. {
  54. public:
  55. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons) = 0;
  56. };
  57. // 过滤为男性
  58. class MaleCriteria : public ICriteria
  59. {
  60. public:
  61. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  62. {
  63. std::vector<Person> resPersons;
  64. for (Person p : persons)
  65. {
  66. if (p.GetGender() == "Male")
  67. {
  68. resPersons.push_back(p);
  69. }
  70. }
  71. return resPersons;
  72. }
  73. };
  74. // 过滤为女性
  75. class FemaleCriteria : public ICriteria
  76. {
  77. public:
  78. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  79. {
  80. std::vector<Person> resPersons;
  81. for (Person p : persons)
  82. {
  83. if (p.GetGender() == "Female")
  84. {
  85. resPersons.push_back(p);
  86. }
  87. }
  88. return resPersons;
  89. }
  90. };
  91. // 过滤为已婚
  92. class MaritalCriteria : public ICriteria
  93. {
  94. public:
  95. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  96. {
  97. std::vector<Person> resPersons;
  98. for (Person p : persons)
  99. {
  100. if (p.GetMaritalStatus() == "Married")
  101. {
  102. resPersons.push_back(p);
  103. }
  104. }
  105. return resPersons;
  106. }
  107. };
  108. // 过滤为单身
  109. class SingleCriteria : public ICriteria
  110. {
  111. public:
  112. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  113. {
  114. std::vector<Person> resPersons;
  115. for (Person p : persons)
  116. {
  117. if (p.GetMaritalStatus() == "Single")
  118. {
  119. resPersons.push_back(p);
  120. }
  121. }
  122. return resPersons;
  123. }
  124. };
  125. // 与过滤器
  126. class AndCriteria : public ICriteria
  127. {
  128. public:
  129. AndCriteria(ICriteria* pCriteriaA, ICriteria* pCriteriaB)
  130. {
  131. this->pCriteriaA = pCriteriaA;
  132. this->pCriteriaB = pCriteriaB;
  133. }
  134. ~AndCriteria()
  135. {
  136. delete pCriteriaA;
  137. pCriteriaA = nullptr;
  138. delete pCriteriaB;
  139. pCriteriaB = nullptr;
  140. }
  141. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  142. {
  143. std::vector<Person> resPersons = pCriteriaA->meetCriteria(pCriteriaB->meetCriteria(persons));
  144. return resPersons;
  145. }
  146. private:
  147. ICriteria* pCriteriaA;
  148. ICriteria* pCriteriaB;
  149. };
  150. // 或过滤器
  151. class OrCriteria : public ICriteria
  152. {
  153. public:
  154. OrCriteria(ICriteria* pCriteriaA, ICriteria* pCriteriaB)
  155. {
  156. this->pCriteriaA = pCriteriaA;
  157. this->pCriteriaB = pCriteriaB;
  158. }
  159. ~OrCriteria()
  160. {
  161. delete pCriteriaA;
  162. pCriteriaA = nullptr;
  163. delete pCriteriaB;
  164. pCriteriaB = nullptr;
  165. }
  166. virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons)
  167. {
  168. std::vector<Person> resPersonsA = pCriteriaA->meetCriteria(persons);
  169. std::vector<Person> resPersonsB = pCriteriaB->meetCriteria(persons);
  170. std::vector<Person> resPersons;
  171. std::set_union(resPersonsA.begin(), resPersonsA.end(),
  172. resPersonsB.begin(), resPersonsB.end(), std::back_inserter(resPersons));
  173. return resPersons;
  174. }
  175. private:
  176. ICriteria* pCriteriaA;
  177. ICriteria* pCriteriaB;
  178. };
  179. // 调用示例
  180. int main()
  181. {
  182. std::vector<Person> persons;
  183. persons.push_back(Person(1, "Bob", "Male", "Single"));
  184. persons.push_back(Person(2, "Amy", "Female", "Married"));
  185. persons.push_back(Person(3, "Mike", "Male", "Single"));
  186. persons.push_back(Person(4, "Jhon", "Male", "Single"));
  187. persons.push_back(Person(5, "Jimy", "Male", "Married"));
  188. persons.push_back(Person(6, "Anna", "Female", "Single"));
  189. persons.push_back(Person(7, "Alice", "Female", "Married"));
  190. persons.push_back(Person(8, "Sue", "Female", "Single"));
  191. persons.push_back(Person(9, "Jane", "Female", "Married"));
  192. persons.push_back(Person(10, "Nancy", "Female", "Single"));
  193. // 筛选男性
  194. ICriteria* maleCriteria = new MaleCriteria();
  195. std::vector<Person> males = maleCriteria->meetCriteria(persons);
  196. std::cout << "Males:" << std::endl;
  197. for (Person p : males)
  198. {
  199. std::cout << p.Info() << std::endl;
  200. }
  201. // 筛选单身女性
  202. ICriteria* singleFemaleCriteria = new AndCriteria(new FemaleCriteria(), new SingleCriteria());
  203. std::vector<Person> singleFemales = singleFemaleCriteria->meetCriteria(persons);
  204. std::cout << "Single FeMales:" << std::endl;
  205. for (Person p : singleFemales)
  206. {
  207. std::cout << p.Info() << std::endl;
  208. }
  209. }
>>>
Males:
Person : [Name : Bob, Gender : Male, Marital Status : Single]
Person : [Name : Mike, Gender : Male, Marital Status : Single]
Person : [Name : Jhon, Gender : Male, Marital Status : Single]
Person : [Name : Jimy, Gender : Male, Marital Status : Married]
Single FeMales:
Person : [Name : Anna, Gender : Female, Marital Status : Single]
Person : [Name : Sue, Gender : Female, Marital Status : Single]
Person : [Name : Nancy, Gender : Female, Marital Status : Single]