0%

【设计模式】Filter/Criteria Pattern 过滤器模式/标准模式

过滤器模式/标准模式 理解剖析以及应用

过滤器模式/标准模式

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

意图

解决问题

对数据进行筛选的场景

何时使用?

当需要对某一组对象进行筛选的时候(比如女澡堂只让女生进,男澡堂只让男生进)

应用环境举例

  1. Spring MVC 中的过滤器,用来过滤掉某些请求。
  2. 敏感词过滤、舆情监测。
  3. 需要对对象列表(或数据列表)进行校验、审查或预处理的场景。
  4. 对网络接口的请求和响应进行拦截,例如对每一个请求和响应记录日志,一遍日后分析。

优点

简单,解耦,使用方便。

缺点

  1. 导致系统成批操作;
  2. 需协调数据流;
  3. 性能较低,每个过滤器对每一个元素都会进行遍历。如果有n个元素,m个过滤器,则负责度为O(mn)

类图

过滤器模式中主要有三个角色,在设计过滤模式时要找到并区分这些角色。

  • 过滤的目标:即要被过滤的对象,通常是一个对象数组(对象列表)。
  • 过滤器:负责过滤不需要的对象,一般一个规则对应一个类。
  • 过滤器链:即过滤器的集合,负责管理和维护过滤器,用这个对象进行过滤器,它包含的每一个子过滤器都会进行一次过滤。这个类并不总是必要的,

但如果有多个过滤器,有这个类会带来极大的便利。

实现

实例

我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。
CriteriaPatternDemo 类使用 Criteria 对象,基于各种标准和它们的结合来过滤 Person 对象的列表。

  • 创建一个类,在该类上应用标准。
    Person.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Person {

    private String name;
    private String gender;
    private String maritalStatus;

    public Person(String name,String gender,String maritalStatus){
    this.name = name;
    this.gender = gender;
    this.maritalStatus = maritalStatus;
    }

    public String getName() {
    return name;
    }
    public String getGender() {
    return gender;
    }
    public String getMaritalStatus() {
    return maritalStatus;
    }
    }
  • 为标准(Criteria)创建一个接口。
    Criteria.java
    1
    2
    3
    4
    5
    import java.util.List;

    public interface Criteria {
    public List<Person> meetCriteria(List<Person> persons);
    }
  • 创建实现了 Criteria 接口的实体类。
    CriteriaMale.java(标准男性)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import java.util.ArrayList;
    import java.util.List;

    public class CriteriaMale implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
    List<Person> malePersons = new ArrayList<Person>();
    for (Person person : persons) {
    //遍历只保留MALE的数据
    if(person.getGender().equalsIgnoreCase("MALE")){
    malePersons.add(person);
    }
    }
    return malePersons;
    }
    }
    CriteriaFemale.java (标准女性)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import java.util.ArrayList;
    import java.util.List;

    public class CriteriaFemale implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
    List<Person> femalePersons = new ArrayList<Person>();
    for (Person person : persons) {
    //遍历只保留FEMALE的数据
    if(person.getGender().equalsIgnoreCase("FEMALE")){
    femalePersons.add(person);
    }
    }
    return femalePersons;
    }
    }
    CriteriaSingle.java (标准单身)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import java.util.ArrayList;
    import java.util.List;

    public class CriteriaSingle implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
    List<Person> singlePersons = new ArrayList<Person>();
    for (Person person : persons) {
    //遍历只保留SINGLE的数据
    if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){
    singlePersons.add(person);
    }
    }
    return singlePersons;
    }
    }
    AndCriteria.java (且标准)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import java.util.List;

    public class AndCriteria implements Criteria {

    private Criteria criteria;
    private Criteria otherCriteria;
    //实例化时传入2种标准实例
    public AndCriteria(Criteria criteria, Criteria otherCriteria) {
    this.criteria = criteria;
    this.otherCriteria = otherCriteria;
    }

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
    //分别用两种标准过滤数据
    List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
    return otherCriteria.meetCriteria(firstCriteriaPersons);
    }
    }
    OrCriteria.java (或标准)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import java.util.List;

    public class OrCriteria implements Criteria {

    private Criteria criteria;
    private Criteria otherCriteria;

    //实例化时传入2种标准实例
    public OrCriteria(Criteria criteria, Criteria otherCriteria) {
    this.criteria = criteria;
    this.otherCriteria = otherCriteria;
    }

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
    //分别用两种标准过滤数据
    List<Person> firstCriteriaItems = criteria.meetCriteria(persons);
    List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons);
    //将两种标准组合为一组数据返回
    for (Person person : otherCriteriaItems) {
    if(!firstCriteriaItems.contains(person)){//去重
    firstCriteriaItems.add(person);
    }
    }
    return firstCriteriaItems;
    }
    }
  • 使用不同的标准(Criteria)和它们的结合来过滤 Person 对象的列表。
    CriteriaPatternDemo.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    import java.util.ArrayList; 
    import java.util.List;

    public class CriteriaPatternDemo {
    public static void main(String[] args) {
    // 数据列表
    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person("Robert","Male", "Single"));
    persons.add(new Person("John","Male", "Married"));
    persons.add(new Person("Laura","Female", "Married"));
    persons.add(new Person("Diana","Female", "Single"));
    persons.add(new Person("Mike","Male", "Single"));
    persons.add(new Person("Bobby","Male", "Single"));
    // 规则
    Criteria male = new CriteriaMale();
    Criteria female = new CriteriaFemale();
    Criteria single = new CriteriaSingle();
    Criteria singleMale = new AndCriteria(single, male);
    Criteria singleOrFemale = new OrCriteria(single, female);
    // 过滤并输出
    System.out.println("Males: ");
    printPersons(male.meetCriteria(persons));

    System.out.println("\nFemales: ");
    printPersons(female.meetCriteria(persons));

    System.out.println("\nSingle Males: ");
    printPersons(singleMale.meetCriteria(persons));

    System.out.println("\nSingle Or Females: ");
    printPersons(singleOrFemale.meetCriteria(persons));
    }

    public static void printPersons(List<Person> persons){
    for (Person person : persons) {
    System.out.println("Person : [ Name : " + person.getName()
    +", Gender : " + person.getGender()
    +", Marital Status : " + person.getMaritalStatus()
    +" ]");
    }
    }
    }
    结果:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Males: 
    Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
    Person : [ Name : John, Gender : Male, Marital Status : Married ]
    Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
    Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

    Females:
    Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
    Person : [ Name : Diana, Gender : Female, Marital Status : Single ]

    Single Males:
    Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
    Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
    Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

    Single Or Females:
    Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
    Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
    Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
    Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
    Person : [ Name : Laura, Gender : Female, Marital Status : Married ]

感谢查阅