过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种结构型设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。说的通俗些就是把一个集合对象根据过滤条件筛选出自己想要的对象。
抽象过滤器角色(AbstractFilter):负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
具体过滤器角色(ConcreteFilter):该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
被过滤的主体角色(Subject):一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。
ICriteria : 抽象过滤器角色,定义了抽象接口doFilter
CCriteriaMale: 具体的过滤器角色,过滤male
CCriteriaFemale: 具体的过滤器角色,过滤female
CCriteriaEducation: 具体的过滤器角色,过滤指定学历的
CCriteriaAboveAge: 具体的过滤器角色,过滤大于某个年龄的
CCriteriaAnd:具体的过滤器角色,实现两个具体的过滤器的逻辑与
CCriteriaOr:具体的过滤器角色,实现两个具体的过滤器的逻辑或
CPerson:?被过滤的主体角色
主体角色和过滤器代码如下:FilterMode.h
#ifndef _FILTER_MODE_H_
#define _FILTER_MODE_H_
#include <string>
#include <vector>
//被过滤的实体类
class CPerson
{
public:
explicit CPerson(const std::string& name, const std::string& sex, int age, const std::string& education)
: m_name(name), m_sex(sex), m_age(age), m_education(education) {}
~CPerson() {}
public:
std::string name() const { return m_name; }
std::string sex() const { return m_sex; }
int age() const { return m_age; }
std::string education() const { return m_education; }
std::string toString() const {
return std::string("[name:") + m_name + std::string(";sex:") + m_sex + std::string(";age:") + std::to_string(m_age)
+ std::string(";education:") + m_education + std::string("]");
}
private:
std::string m_name;
std::string m_sex;
int m_age;
std::string m_education;
};
//抽象过滤器
class ICriteria {
public:
virtual std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) = 0;
};
//具体过滤器:过滤male
class CCriteriaMale : public ICriteria
{
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> malePersons;
for (auto& it : persons) {
if (0 == it->sex().compare("male")) {
malePersons.push_back(it);
}
}
return malePersons;
}
};
//具体过滤器:过滤female
class CCriteriaFemale : public ICriteria
{
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> femalePersons;
for (auto& it : persons) {
if (0 == it->sex().compare("female")) {
femalePersons.push_back(it);
}
}
return femalePersons;
}
};
//具体过滤器:过滤学历
class CCriteriaEducation : public ICriteria
{
public:
explicit CCriteriaEducation(const std::string& education) :m_education(education) {}
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> eduPersons;
for (auto& it : persons) {
if (0 == it->education().compare(m_education)) {
eduPersons.push_back(it);
}
}
return eduPersons;
}
private:
std::string m_education;
};
//具体过滤器:过滤年龄
class CCriteriaAboveAge : public ICriteria
{
public:
explicit CCriteriaAboveAge(int age) : m_age(age) {}
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> agePersons;
for (auto& it : persons) {
if (it->age() > m_age) {
agePersons.push_back(it);
}
}
return agePersons;
}
private:
int m_age;
};
//具体过滤器:两个过滤器的逻辑与
class CCriteriaAnd : public ICriteria
{
public:
explicit CCriteriaAnd(ICriteria* pCriteria1, ICriteria* pCriteria2)
: m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> andPersons = m_criteria1->doFilter(persons);
return m_criteria2->doFilter(andPersons);
}
private:
ICriteria* m_criteria1;
ICriteria* m_criteria2;
};
//具体过滤器:两个过滤器的逻辑或
class CCriteriaOr : public ICriteria
{
public:
explicit CCriteriaOr(ICriteria* pCriteria1, ICriteria* pCriteria2)
: m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}
public:
std::vector<CPerson*> doFilter(const std::vector<CPerson*>& persons) override {
std::vector<CPerson*> orPersons = m_criteria1->doFilter(persons);
std::vector<CPerson*> orPersons1 = m_criteria2->doFilter(persons);
for (auto& it : orPersons1) {
if (std::find_if(orPersons.begin(), orPersons.end(),
[=](auto& iter) {return it == iter; }) == orPersons.end()) {
orPersons.push_back(it);
}
}
return orPersons;
}
private:
ICriteria* m_criteria1;
ICriteria* m_criteria2;
};
#endif
使用不同的标准(Criteria)和它们的结合来过滤CPerson对象的列表,测试代码如下:
#include "FilterMode.h"
static void printPerson(const std::string& tip, std::vector<CPerson*>& persons) {
qDebug() << tip.data();
for (auto& it : persons) {
qDebug() << it->toString().data();
}
}
void main() {
std::vector<CPerson*> vecTemp;
std::vector<CPerson*> vecPersons;
vecPersons.push_back(new CPerson("liu bin", "male", 39, "benke"));
vecPersons.push_back(new CPerson("li xiang", "female", 25, "zhuanke"));
vecPersons.push_back(new CPerson("he nan shan", "male", 44, "boshi"));
vecPersons.push_back(new CPerson("san ling", "female", 56, "suoshi"));
vecPersons.push_back(new CPerson("guo dong", "male", 27, "zhuanke"));
vecPersons.push_back(new CPerson("jing gang shan", "female", 32, "suoshi"));
vecPersons.push_back(new CPerson("shan shan", "female", 41, "benke"));
vecPersons.push_back(new CPerson("mei duo", "male", 10, "xiaoxue"));
ICriteria* pMaleCriteria = new CCriteriaMale();
ICriteria* pFemaleCriteria = new CCriteriaFemale();
ICriteria* pAgeCriteria = new CCriteriaAboveAge(26);
ICriteria* pEduCriteria = new CCriteriaEducation("benke");
ICriteria* pAndCriteria = new CCriteriaAnd(pMaleCriteria, pEduCriteria);
ICriteria* pOrCriteria = new CCriteriaOr(pFemaleCriteria, pAgeCriteria);
vecTemp = pMaleCriteria->doFilter(vecPersons);
printPerson("male: ", vecTemp);
vecTemp = pFemaleCriteria->doFilter(vecPersons);
printPerson("female: ", vecTemp);
vecTemp = pAgeCriteria->doFilter(vecPersons);
printPerson("age>26: ", vecTemp);
vecTemp = pEduCriteria->doFilter(vecPersons);
printPerson("benke: ", vecTemp);
vecTemp = pAndCriteria->doFilter(vecPersons);
printPerson("benke and male: ", vecTemp);
vecTemp = pOrCriteria->doFilter(vecPersons);
printPerson("age>26 or female: ", vecTemp);
for (auto& it : vecTemp) {
delete it;
}
delete pMaleCriteria;
delete pFemaleCriteria;
delete pAgeCriteria;
delete pEduCriteria;
delete pAndCriteria;
delete pOrCriteria;
}
输出:
male:
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:mei duo;sex:male;age:10;education:xiaoxue]
female:
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]
age>26:
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:san ling;sex:female;age:56;education:suoshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]
benke:
[name:liu bin;sex:male;age:39;education:benke]
[name:shan shan;sex:female;age:41;education:benke]
benke and male:
[name:liu bin;sex:male;age:39;education:benke]
age>26 or female:
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
?