一、什么是过滤器模式
过滤器模式(Filter Pattern)又称标准模式(Criteria Pattern)是一种设计模式,属于结构型模式。这种模式允许开发人员使用不同的标准来过滤一组对象,通过运算逻辑以解耦的方式将它们连接起来。过滤器模式可结合多个标准来获得单一标准。说白了,就是按条件筛选一组对象出来。
二、过滤器模式的实现
2.1 过滤器模式角色
-
- 抽象过滤器角色(AbstractFilter) :负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
-
- 具体过滤器角色(ConcreteFilter) :该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
-
- 被过滤的主体角色(Subject) :一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。
2.2 过滤器模式类图
2.3 过滤器模式举例
场景: 一群人当中有按性别划分为男人、女人;按婚姻状态划分为未婚、已婚、离异、丧偶。当需要根据按指定性别,婚姻状态寻找特定人群,则此时就很适用过滤器模式。
2.4 过滤器模式代码实现
辅助枚举类
package com.ssm.user.designPattern.filterPattern;
public enum GenderEnum {
MALE(1,"男"),
FEMALE(2,"女"),
HERMAPHRODITE(3,"人妖"),
;
private int code;
private String msg;
GenderEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.ssm.user.designPattern.filterPattern;
public enum MaritalTypeEnum {
UNMARRIED(1,"未婚"),
MARRIED(2,"已婚"),
DIVORCED(3,"离婚"),
WIDOWED(4,"丧偶"),
;
private int code;
private String desc;
MaritalTypeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}
被过滤的主体角色
package com.ssm.user.designPattern.filterPattern;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class People {
private String name; //姓名
private GenderEnum genderEnum; //性别
private MaritalTypeEnum maritalTypeEnum; //婚姻状况
}
具体过滤器角色
package com.ssm.user.designPattern.filterPattern;
import java.util.ArrayList;
import java.util.List;
public class GenderFilter implements Filter{
private GenderEnum genderEnum;
public GenderFilter(GenderEnum genderEnum) {
// 在构造方法时指定性别
this.genderEnum = genderEnum;
}
@Override
public List<People> doFilter(List<People> peopleList) {
List<People> result = new ArrayList<>();
for (People people : peopleList) {
if (this.genderEnum.equals(people.getGenderEnum())) {
result.add(people);
}
}
return result;
}
}
package com.ssm.user.designPattern.filterPattern;
import java.util.ArrayList;
import java.util.List;
public class MaritalTypeFilter implements Filter{
private MaritalTypeEnum maritalTypeEnum;
public MaritalTypeFilter(MaritalTypeEnum maritalTypeEnum) {
// 在构造方法时指定婚姻
this.maritalTypeEnum = maritalTypeEnum;
}
@Override
public List<People> doFilter(List<People> peopleList) {
List<People> result = new ArrayList<>();
for (People people : peopleList) {
if (this.maritalTypeEnum.equals(people.getMaritalTypeEnum())) {
result.add(people);
}
}
return result;
}
}
抽象过滤器角色
package com.ssm.user.designPattern.filterPattern;
import java.util.List;
public interface Filter {
List<People> doFilter(List<People> peopleList);
}
测试
package com.ssm.user.designPattern.filterPattern;
import java.util.ArrayList;
import java.util.List;
public class filterPatternDemo {
public static void main(String[] args) {
// 数据初始化
List<People> personList = new ArrayList<People>();
personList.add(new People("张美丽", GenderEnum.FEMALE, MaritalTypeEnum.DIVORCED));
personList.add(new People("老张", GenderEnum.MALE, MaritalTypeEnum.MARRIED));
personList.add(new People("小明", GenderEnum.MALE, MaritalTypeEnum.UNMARRIED));
personList.add(new People("李花花", GenderEnum.FEMALE, MaritalTypeEnum.MARRIED));
personList.add(new People("王五", GenderEnum.MALE, MaritalTypeEnum.MARRIED));
personList.add(new People("王麻子", GenderEnum.MALE, MaritalTypeEnum.WIDOWED));
//过滤女性
GenderFilter girlFilter = new GenderFilter(GenderEnum.FEMALE);
List<People> people = girlFilter.doFilter(personList);
System.out.println(people);
//过滤男性且未婚
GenderFilter boyFilter = new GenderFilter(GenderEnum.MALE); //男性过滤器
MaritalTypeFilter maritalTypeFilter = new MaritalTypeFilter(MaritalTypeEnum.UNMARRIED); //未婚过滤器
List<People> people1 = maritalTypeFilter.doFilter(boyFilter.doFilter(personList)); //双重过滤
System.out.println(people1);
}
}
三、过滤器模式的特点
3.1 优点
-
灵活性:通过定义不同的过滤器实现类和不同的谓词(Predicate),可以灵活地对数据集合进行过滤,可结合多个标准来获取唯一标准,从而得到符合不同条件的子集,其设计概念是支持可插拔设计的。
-
可扩展性:允许开发人员使用不同的标准来过滤一组对象,在实现过滤器模式时,可添加、组合和重用不同的过滤器,从而轻松扩展过滤器的功能
-
简单性:过滤器模式非常简单且易于理解。它将数据集合和过滤器分开,使得代码更加清晰和易于维护
-
有序性:过滤器是被设计为一组组的过滤装置,要实现数据过滤,实现对数据顺序性过滤的要求。
-
独立性:每种过滤器必须是独立的实体,其状态不受其它过滤器的影响,每个过滤器都有独立的数据输入输出接口,只要各个过滤器之间传送的数据遵守共同的规约就可以相连接。
3.2 缺点
-
性能问题:当数据集合非常大时,过滤器模式可能会导致性能问题。每次过滤都需要遍历整个数据集合,这可能会降低程序的运行效率
-
配置复杂性:当需要组合多个过滤器时,可能需要编写大量的配置代码,这可能会增加代码的复杂性。
3.3 注意事项
大数据量时,需要考虑其处理性能