Java设计模式:过滤器模式的介绍及代码演示

168 阅读3分钟

过滤器模式介绍

过滤器模式是指,通过逻辑运算从目标数据集中读取符合条件的数据的一种设计模式,筛选的逻辑独立于目标数据,维护方便,可以自由的修改过滤逻辑或添加新的过滤逻辑。举个例子说明一下,假如现在有一组成绩单,展示了一个班级里面所有学生的考试成绩,现在想要将总分数前三的同学信息筛选出来,那么就需要将每个学生的各科成绩求和然后比较,最终找出成绩排名前三的学生信息。

image.png

简单一句话就是,过滤模式可以根据要求从对象列表中,筛选出符合条件的对象。

过滤器模式示例代码

过滤器模式的核心是过滤器,所以要定义一个类去实现过滤逻辑,并且过滤器针对的是一组对象集,所以要有一个类表示对象集中的具体对象,最后通过一个客户端或者测试类去调度程序对数据进行过滤。现在要实现的需求是在一份成绩单中,过滤出成绩排名前三的学生成绩单信息,代码示例如下:

创建一个过滤器的抽象
抽象类中包含过滤的方法,定义了一个表示成绩单的集合参数

/**
 * 过滤器抽象
 */
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;
		}
	}
}

提示

  1. 上面的类中,创建了一个获取总成绩的方法,因为要用总成绩排名。
  2. 重写了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);就是执行过滤器的代码,返回了过滤后的对象集合,运行结果如下:

image.png 运行的结果没有任何问题,现在就已经成功创建了过滤器模式的代码!

总结

过滤器模式属于结构型模式,它可以从原有的对象集合中,过滤出符合条件的新对象集合。我们可以根据需要,定义各种各样的过滤器,分别拿到符合各自条件的对象集合。所以,当需要对一组对象进行筛选的时候,就应该选择使用过滤器模式,从而避免在程序中“硬编码”导致的代码高耦合。过滤器模式体现出了面向对象中的封装特性,提高了程序得灵活性和可扩展性。