设计模式系列之过滤器模式(Chriteria Pattern)
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。我们的演示类使用 Criteria 对象,基于各种标准和它们的结合来过滤 Person 对象的列表。
简单的对象的创建
这里写了一些简单的额POJO对象,用于演示使用,主要就是Person和枚举类型.
- @Data 是Lombok提供的插件支持,没有的话,可以手写setter/getter方法
Person
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@ToString
public class Person {
private String name;
private String gender;
private int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
}
GenderStatus
性别状态信息
/**
* 作用:
*
* <p>时间:2018/6/26 22:08
*
* <p>位置:com.tao.example.design.criteria.entity
*
* @author Yan - tao - zhoutao825638@vip.qq.com
*/
public enum GenderStatus {
FEMALE,
MALE
}
过滤器的实现
过滤器接口
public interface Criteria {
/**
* 过滤器
*
* @param persons
* @return
*/
List<Person> meetCriteria(List<Person> persons);
}
基本过滤器
男性过滤器
public class CriteriaMale implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> collect =
persons
.stream()
.filter(
person -> {
return person.getGender().equals(GenderStatus.MALE.name());
})
.collect(Collectors.toList());
return collect;
}
}
女性过滤器
public class CriteriaFemale implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> collect =
persons
.stream()
.filter(
person -> {
return person.getGender().equals(GenderStatus.FEMALE.name());
})
.collect(Collectors.toList());
return collect;
}
}
成年过滤器
public class CriteriaAdult implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> personList =
persons.stream().filter(person -> person.getAge() >= 18).collect(Collectors.toList());
return personList;
}
}
逻辑过滤器组合
交集过滤器
提供两个基本过滤器,采用与操作线性过滤
public class AndCriteria implements Criteria {
private Criteria mainCriteria;
private Criteria otherCriteria;
public AndCriteria(Criteria mainCriteria, Criteria otherCriteria) {
this.mainCriteria = mainCriteria;
this.otherCriteria = otherCriteria;
}
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> mainCriteriaPersons = mainCriteria.meetCriteria(persons);
List<Person> personList = otherCriteria.meetCriteria(mainCriteriaPersons);
return personList;
}
}
并集过滤器
原理和交集过滤器类似
public class OrCriteria implements Criteria {
private Criteria mainCriteria;
private Criteria otherCriteria;
public OrCriteria(Criteria mainCriteria, Criteria otherCriteria) {
this.mainCriteria = mainCriteria;
this.otherCriteria = otherCriteria;
}
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> mainCriteriaPersons = mainCriteria.meetCriteria(persons);
List<Person> otherCriteriaPersons = otherCriteria.meetCriteria(persons);
mainCriteriaPersons.forEach(
person -> {
if (!otherCriteriaPersons.contains(mainCriteriaPersons)) {
otherCriteriaPersons.add(person);
}
});
return otherCriteriaPersons;
}
}
过滤效果测试
测试代码
使用如下代码测试
public class TestCriteriaPattern {
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("赵清雅", GenderStatus.FEMALE.name(), 15));
persons.add(new Person("李建岺", GenderStatus.MALE.name(), 16));
persons.add(new Person("冯蕙茞", GenderStatus.FEMALE.name(), 17));
persons.add(new Person("周踵武", GenderStatus.MALE.name(), 18));
persons.add(new Person("杨畹兮", GenderStatus.FEMALE.name(), 15));
persons.add(new Person("姜驰骛", GenderStatus.MALE.name(), 21));
// 创建过滤器
CriteriaFemale criteriaFemale = new CriteriaFemale();
CriteriaMale criteriaMale = new CriteriaMale();
CriteriaAdult criteriaAdult = new CriteriaAdult();
AndCriteria maleAndAdult = new AndCriteria(criteriaMale, criteriaAdult);
AndCriteria femaleAndAdult = new AndCriteria(criteriaFemale, criteriaAdult);
OrCriteria femaleOrAdult = new OrCriteria(criteriaFemale, criteriaAdult);
printPersons("男性过滤器", criteriaMale.meetCriteria(persons));
printPersons("女性过滤器", criteriaFemale.meetCriteria(persons));
printPersons("成年过滤器", criteriaAdult.meetCriteria(persons));
printPersons("成年男性过滤器", maleAndAdult.meetCriteria(persons));
printPersons("成年女过滤器", femaleAndAdult.meetCriteria(persons));
printPersons("女性或成年过滤器", femaleOrAdult.meetCriteria(persons));
}
public static void printPersons(String criteriaName, List<Person> personList) {
System.out.println(criteriaName);
if (personList.size() == 0){
System.out.println("\t 没有找到");
}
personList.forEach(
person -> {
System.out.println("\t" + person);
});
System.out.println("---------------------");
}
}
测试输出
男性过滤器
Person(name=李建岺, gender=MALE, age=16)
Person(name=周踵武, gender=MALE, age=18)
Person(name=姜驰骛, gender=MALE, age=21)
---------------------
女性过滤器
Person(name=赵清雅, gender=FEMALE, age=15)
Person(name=冯蕙茞, gender=FEMALE, age=17)
Person(name=杨畹兮, gender=FEMALE, age=15)
---------------------
成年过滤器
Person(name=周踵武, gender=MALE, age=18)
Person(name=姜驰骛, gender=MALE, age=21)
---------------------
成年男性过滤器
Person(name=周踵武, gender=MALE, age=18)
Person(name=姜驰骛, gender=MALE, age=21)
---------------------
成年女过滤器
没有找到
---------------------
女性或成年过滤器
Person(name=周踵武, gender=MALE, age=18)
Person(name=姜驰骛, gender=MALE, age=21)
Person(name=赵清雅, gender=FEMALE, age=15)
Person(name=冯蕙茞, gender=FEMALE, age=17)
Person(name=杨畹兮, gender=FEMALE, age=15)
---------------------