设计模式系列之过滤器模式(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)
---------------------
posted @ 2019-02-15 10:31  燕归来兮  阅读(336)  评论(0编辑  收藏  举报