一、简介
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
二、过滤器模式实例
实例介绍
假如某地政府为了帮助无业人员就业,统计了一批36岁市民的就业情况。政府拿到名单后,过滤出无业人员帮助就业。
为了完成这个项目,我们需要建造:
1)人员信息类 Person;
2)标准抽象类 Criteria,提供按照某标准过滤的接口 meetCriteria;
3)标准具体类,继承Criteria,定义不同的过滤标准,实现meetCriteria接口;
代码实现
1)人员信息类 Person
class Person
{
public:
Person(string name, int age, string gdr, string work)
:_name(name)
, _age(age)
, _gender(gdr)
, _work(work) {}
~Person() {}
void show()
{
cout << "**********档案记录***********" << endl;
cout << "姓名:" <<_name << endl;
cout << "性别:" << _gender << endl;
cout << "工作:" << _work << endl;
}
public:
string _name; //姓名
int _age; //年龄
string _gender; //性别
string _work; //工作
};
2)标准抽象类 Criteria,提供按照某标准过滤的接口 meetCriteria;
class Criteria
{
public:
//定义过滤器接口:按照某一标准过滤出对象指针列表,这一标准由继承了Criteria的实体类具体定义
virtual vector<Person*> meetCriteria(vector<Person*> all) = 0;
};
3)标准具体类,继承Criteria,定义不同的过滤标准,实现meetCriteria接口;
其中定义了过滤女性、男性、和无业者的类,并且提供了与和或这两种可以提供组合2个过滤器服务的过滤器。
//女性过滤器
class CriteriaFemale : public Criteria
{
vector<Person*> meetCriteria(vector<Person*> allPerson)
{
vector<Person*> per;
for (auto it: allPerson)
{
if ("女" == it->_gender)
{
per.push_back(it);
}
}
return per;
}
};
//男性过滤器
class CriteriaMale : public Criteria
{
vector<Person*> meetCriteria(vector<Person*> allPerson)
{
vector<Person*> per;
for (auto it : allPerson)
{
if ("男" == it->_gender)
{
per.push_back(it);
}
}
return per;
}
};
//无业者过滤器
class CriteriaUnemployed : public Criteria
{
vector<Person*> meetCriteria(vector<Person*> allPerson)
{
vector<Person*> per;
for (auto it : allPerson)
{
if ("" == it->_work)
{
per.push_back(it);
}
}
return per;
}
};
//逻辑关系:与 的过滤器
class AndCriteria :public Criteria
{
public:
AndCriteria(Criteria *p1, Criteria *p2)
:_pCriteria1(p1)
,_pCriteria2(p2) {}
~AndCriteria()
{
if (nullptr != _pCriteria1)
{
delete _pCriteria1;
_pCriteria1 = nullptr;
}
if (nullptr != _pCriteria2)
{
delete _pCriteria2;
_pCriteria2 = nullptr;
}
}
vector<Person*> meetCriteria(vector<Person*> allPerson)
{
vector<Person*> per;
if (nullptr == _pCriteria1 || nullptr == _pCriteria2)
{
return per;
}
//先以标准1过滤
per = _pCriteria1->meetCriteria(allPerson);
//再以标准2过滤标准1的结果
per = _pCriteria2->meetCriteria(per);
return per;
}
private:
Criteria *_pCriteria1;
Criteria *_pCriteria2;
};
//逻辑关系:或 的过滤器
class OrCriteria :public Criteria
{
public:
OrCriteria(Criteria *p1, Criteria *p2)
:_pCriteria1(p1)
, _pCriteria2(p2) {}
~OrCriteria()
{
if (nullptr != _pCriteria1)
{
delete _pCriteria1;
_pCriteria1 = nullptr;
}
if (nullptr != _pCriteria2)
{
delete _pCriteria2;
_pCriteria2 = nullptr;
}
}
vector<Person*> meetCriteria(vector<Person*> allPerson)
{
vector<Person*> per;
if (nullptr == _pCriteria1 || nullptr == _pCriteria2)
{
return per;
}
//以标准1和标准2分别过滤整个样本
per = _pCriteria1->meetCriteria(allPerson);
vector<Person*> per2;
per2 = _pCriteria2->meetCriteria(allPerson);
//合并两个过滤结果
for (auto it:per2)
{
per.push_back(it);
}
return per;
}
private:
Criteria *_pCriteria1;
Criteria *_pCriteria2;
};
4)使用
int main(int argc, char *argv[])
{
Person p1("A", 36, "男", "法官");
Person p2("B", 36, "男", "教师");
Person p3("C", 36, "男", "农民");
Person p4("D", 36, "男", "");
Person p5("E", 36, "男", "");
Person p6("F", 36, "男", "");
Person p7("G", 36, "女", "保洁");
Person p8("H", 36, "女", "医生");
Person p9("J", 36, "女", "工程师");
Person p10("K", 36, "女", "");
Person p11("L", 36, "女", "");
vector< Person*> allPerson;
allPerson.push_back(&p1);
allPerson.push_back(&p2);
allPerson.push_back(&p3);
allPerson.push_back(&p4);
allPerson.push_back(&p5);
allPerson.push_back(&p6);
allPerson.push_back(&p7);
allPerson.push_back(&p8);
allPerson.push_back(&p9);
allPerson.push_back(&p10);
allPerson.push_back(&p11);
//女性过滤器
CriteriaFemale *female = new CriteriaFemale();
//男性过滤器
CriteriaMale *male = new CriteriaMale();
//无业过滤器
CriteriaUnemployed *unemployed = new CriteriaUnemployed();
//女性无业者列表
AndCriteria *and1 = new AndCriteria(female, unemployed);
vector< Person*> per = and1->meetCriteria(allPerson);
cout << "女性无业者列表 :" << endl;
for (auto it : per)
{
it->show();
}
//男性无业者列表
AndCriteria *and2 = new AndCriteria(male, unemployed);
per = and2->meetCriteria(allPerson);
cout << endl << "男性无业者列表 :" << endl;
for (auto it : per)
{
it->show();
}
system("pause");
return 0;
}
5)输出