过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
意图
对同一组对象能够以不同过滤条件筛选出来
主要解决
能够以不同条件或条件的组合筛选对象
何时使用
一组对象需要根据属性作筛选时
如何解决
使用过滤器类进行筛选
应用实例
- 对用户信息根据不同条件如性别、婚姻状况筛选
- 对车辆根据根据不同条件如颜色、款式筛选
优点
能使用不同过滤器的组合方便的筛选对象
缺点
过滤器依赖对象的结构,对象属性变化时过滤器也需要变化,如示例中的婚姻状况增加了一种”离异”,则需要增加或修改过滤器
注意事项
过滤器应该尽量简单,复杂的过滤器应使用多个简单过滤器组合得到,这样当对象属性变化时,过滤器的改动能尽量小
示例
整理用户信息时,使用过滤器方便的筛选不同条件的人,比如筛选男性、女性、单身女性等等
#include "pch.h"#include <iostream>#include <sstream>#include <vector>#include <algorithm>// 人class Person{public:Person(int ID, std::string name, std::string gender, std::string maritalStatus){if ("Male" != gender && "Female" != gender) { throw "Invalid Parameter"; }if ("Single" != maritalStatus && "Married" != maritalStatus) { throw "Invalid Parameter"; }this->ID = ID;this->name = name;this->gender = gender;this->maritalStatus = maritalStatus;}std::string GetName(){return this->name;}std::string GetGender(){return this->gender;}std::string GetMaritalStatus(){return this->maritalStatus;}std::string Info(){std::string info;std::ostringstream ostr;ostr << "Person : [Name : " << name << ", Gender : " << gender << ", Marital Status : " << maritalStatus << "]";return ostr.str();}bool operator == (const Person & person) const{return this->ID == person.ID;}bool operator < (const Person & person) const{return this->ID < person.ID;}private:int ID;std::string name;std::string gender;std::string maritalStatus;};class ICriteria{public:virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons) = 0;};// 过滤为男性class MaleCriteria : public ICriteria{public:virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersons;for (Person p : persons){if (p.GetGender() == "Male"){resPersons.push_back(p);}}return resPersons;}};// 过滤为女性class FemaleCriteria : public ICriteria{public:virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersons;for (Person p : persons){if (p.GetGender() == "Female"){resPersons.push_back(p);}}return resPersons;}};// 过滤为已婚class MaritalCriteria : public ICriteria{public:virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersons;for (Person p : persons){if (p.GetMaritalStatus() == "Married"){resPersons.push_back(p);}}return resPersons;}};// 过滤为单身class SingleCriteria : public ICriteria{public:virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersons;for (Person p : persons){if (p.GetMaritalStatus() == "Single"){resPersons.push_back(p);}}return resPersons;}};// 与过滤器class AndCriteria : public ICriteria{public:AndCriteria(ICriteria* pCriteriaA, ICriteria* pCriteriaB){this->pCriteriaA = pCriteriaA;this->pCriteriaB = pCriteriaB;}~AndCriteria(){delete pCriteriaA;pCriteriaA = nullptr;delete pCriteriaB;pCriteriaB = nullptr;}virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersons = pCriteriaA->meetCriteria(pCriteriaB->meetCriteria(persons));return resPersons;}private:ICriteria* pCriteriaA;ICriteria* pCriteriaB;};// 或过滤器class OrCriteria : public ICriteria{public:OrCriteria(ICriteria* pCriteriaA, ICriteria* pCriteriaB){this->pCriteriaA = pCriteriaA;this->pCriteriaB = pCriteriaB;}~OrCriteria(){delete pCriteriaA;pCriteriaA = nullptr;delete pCriteriaB;pCriteriaB = nullptr;}virtual std::vector<Person> meetCriteria(const std::vector<Person>& persons){std::vector<Person> resPersonsA = pCriteriaA->meetCriteria(persons);std::vector<Person> resPersonsB = pCriteriaB->meetCriteria(persons);std::vector<Person> resPersons;std::set_union(resPersonsA.begin(), resPersonsA.end(),resPersonsB.begin(), resPersonsB.end(), std::back_inserter(resPersons));return resPersons;}private:ICriteria* pCriteriaA;ICriteria* pCriteriaB;};// 调用示例int main(){std::vector<Person> persons;persons.push_back(Person(1, "Bob", "Male", "Single"));persons.push_back(Person(2, "Amy", "Female", "Married"));persons.push_back(Person(3, "Mike", "Male", "Single"));persons.push_back(Person(4, "Jhon", "Male", "Single"));persons.push_back(Person(5, "Jimy", "Male", "Married"));persons.push_back(Person(6, "Anna", "Female", "Single"));persons.push_back(Person(7, "Alice", "Female", "Married"));persons.push_back(Person(8, "Sue", "Female", "Single"));persons.push_back(Person(9, "Jane", "Female", "Married"));persons.push_back(Person(10, "Nancy", "Female", "Single"));// 筛选男性ICriteria* maleCriteria = new MaleCriteria();std::vector<Person> males = maleCriteria->meetCriteria(persons);std::cout << "Males:" << std::endl;for (Person p : males){std::cout << p.Info() << std::endl;}// 筛选单身女性ICriteria* singleFemaleCriteria = new AndCriteria(new FemaleCriteria(), new SingleCriteria());std::vector<Person> singleFemales = singleFemaleCriteria->meetCriteria(persons);std::cout << "Single FeMales:" << std::endl;for (Person p : singleFemales){std::cout << p.Info() << std::endl;}}
>>>
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]
