过滤器模式介绍
过滤器模式是指,通过逻辑运算从目标数据集中读取符合条件的数据的一种设计模式,筛选的逻辑独立于目标数据,维护方便,可以自由的修改过滤逻辑或添加新的过滤逻辑。举个例子说明一下,假如现在有一组成绩单,展示了一个班级里面所有学生的考试成绩,现在想要将总分数前三的同学信息筛选出来,那么就需要将每个学生的各科成绩求和然后比较,最终找出成绩排名前三的学生信息。
简单一句话就是,过滤模式可以根据要求从对象列表中,筛选出符合条件的对象。
过滤器模式示例代码
过滤器模式的核心是过滤器,所以要定义一个类去实现过滤逻辑,并且过滤器针对的是一组对象集,所以要有一个类表示对象集中的具体对象,最后通过一个客户端或者测试类去调度程序对数据进行过滤。现在要实现的需求是在一份成绩单中,过滤出成绩排名前三的学生成绩单信息,代码示例如下:
创建一个过滤器的抽象
抽象类中包含过滤的方法,定义了一个表示成绩单的集合参数
/**
* 过滤器抽象
*/
public interface FilterAbstract {
List<SchoolReport> filter(List<SchoolReport> data);
}
创建一个过滤器的实现
重写过滤方法,筛选出成绩排名前三的学生成绩信息
/**
* 过滤器实现
*/
public class FilterImpl implements FilterAbstract{
/**
* 过滤出总成绩前三的学生成绩单信息
*/
@Override
public List<SchoolReport> filter(List<SchoolReport> data) {
return data.stream().sorted().limit(3).toList();
}
}
创建一个目标类
需要过滤的具体目标,这里的过滤对象是成绩单列表,所以创建一个成绩单对象,存放学生的成绩信息
/**
* 学生成绩单
*/
public class SchoolReport implements Comparable<SchoolReport>{
//姓名
private String name;
//语文成绩
private float chinese;
//英语成绩
private float english;
//数学成绩
private float math;
public SchoolReport(String name,float chinese,float english,float math) {
this.name = name;
this.chinese = chinese;
this.english = english;
this.math = math;
}
public String getName() {
return name;
}
public float getChinese() {
return chinese;
}
public float getEnglish() {
return english;
}
public float getMath() {
return math;
}
//获取总成绩的方法
public float getTotalScore() {
return chinese + english + math;
}
//定义按分数排序
@Override
public int compareTo(SchoolReport o) {
if(this.getTotalScore()>o.getTotalScore()) {
return -1;
}else if(this.getTotalScore()<o.getTotalScore()) {
return 1;
}else {
return 0;
}
}
}
提示
- 上面的类中,创建了一个获取总成绩的方法,因为要用总成绩排名。
- 重写了
Comparable
的排序方法compareTo()
,因为这里过滤器排名的思路是先按总成绩倒序,然后保留前三个学生的成绩信息。
测试类测试代码
public class test_01 {
public static void main(String[] args) {
List<SchoolReport> reports = new ArrayList<>();
reports.add(new SchoolReport("诺亚",95f,95f,95f));
reports.add(new SchoolReport("迪迦",90f,95f,92f));
reports.add(new SchoolReport("赛迦",90.5f,94.5f,92.5f));
reports.add(new SchoolReport("雷杰多",99f,99f,99f));
System.out.println("学生的成绩单如下:");
reports.forEach(d -> {
System.out.print(d.getName()+":");
System.out.print("语文-"+d.getChinese()+",");
System.out.print("数学-"+d.getChinese()+",");
System.out.print("英语-"+d.getChinese()+",");
System.out.println("总成绩-"+d.getTotalScore());
});
System.out.println("前三名的学生成绩信息:");
FilterAbstract filter = new FilterImpl();
reports = filter.filter(reports);
reports.forEach(d -> {
System.out.print(d.getName()+":");
System.out.print("语文-"+d.getChinese()+",");
System.out.print("数学-"+d.getChinese()+",");
System.out.print("英语-"+d.getChinese()+",");
System.out.println("总成绩-"+d.getTotalScore());
});
}
}
上面的测试代码中,reports = filter.filter(reports);
就是执行过滤器的代码,返回了过滤后的对象集合,运行结果如下:
运行的结果没有任何问题,现在就已经成功创建了过滤器模式的代码!
总结
过滤器模式属于结构型模式,它可以从原有的对象集合中,过滤出符合条件的新对象集合。我们可以根据需要,定义各种各样的过滤器,分别拿到符合各自条件的对象集合。所以,当需要对一组对象进行筛选的时候,就应该选择使用过滤器模式,从而避免在程序中“硬编码”导致的代码高耦合。过滤器模式体现出了面向对象中的封装特性,提高了程序得灵活性和可扩展性。