目录
什么是过滤器模式
过滤器模式(Filter Pattern)又称标准模式(Criteria Pattern)是一种设计模式,属于结构型模式。这种模式允许开发人员使用不同的标准来过滤一组对象,通过运算逻辑以解耦的方式将它们连接起来。过滤器模式可结合多个标准来获得单一标准。说白了,就是按条件筛选一组对象出来。
过滤器模式的实现
过滤器模式角色
- 抽象过滤器角色(AbstractFilter):负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
- 具体过滤器角色(ConcreteFilter):该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
- 被过滤的主体角色(Subject):一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。
过滤器模式类图
过滤器模式举例
场景: 一群人当中有按性别划分为男人、女人;按婚姻状态划分为未婚、已婚、离异、丧偶。当需要根据按指定性别,婚姻状态寻找特定人群,则此时就很适用过滤器模式。
过滤器模式代码实现
抽象过滤器角色
package com.common.demo.pattern.filter;
import java.util.List;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 过滤器接口
* @date 2023/07/11 20:40:59
*/
public interface Filter {
List<People> doFilter(List<People> peopleList);
}
具体过滤器角色
package com.common.demo.pattern.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 婚姻状态过滤器
* @date 2023/07/11 21:24:27
*/
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.getMaritalType())) {
result.add(people);
}
}
return result;
}
}
package com.common.demo.pattern.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 性别过滤器
* @date 2023/07/11 21:21:36
*/
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.getGender())) {
result.add(people);
}
}
return result;
}
}
被过滤的主体角色
package com.common.demo.pattern.filter;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 人实体类
* @date 2023/07/11 20:41:11
*/
public class People {
private String name;
/**
* 1.男-MALE 2.女-FEMALE 3.人妖-HERMAPHRODITE
*/
private GenderEnum gender;
/**
* 1.未婚-UNMARRIED 2.已婚-MARRIED 3.离婚-DIVORCED 4.丧偶-WIDOWED
*/
private MaritalTypeEnum maritalType;
public People() {
}
public People(String name,GenderEnum gender, MaritalTypeEnum maritalType) {
this.name = name;
this.gender = gender;
this.maritalType = maritalType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public GenderEnum getGender() {
return gender;
}
public void setGender(GenderEnum gender) {
this.gender = gender;
}
public MaritalTypeEnum getMaritalType() {
return maritalType;
}
public void setMaritalType(MaritalTypeEnum maritalType) {
this.maritalType = maritalType;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", gender=" + gender +
", maritalType=" + maritalType +
'}';
}
}
辅助枚举类
package com.common.demo.pattern.filter;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 婚姻状态枚举
* @date 2023/07/11 20:49:30
*/
public enum MaritalTypeEnum {
UNMARRIED(1,"未婚"),
MARRIED(2,"已婚"),
DIVORCED(3,"离婚"),
WIDOWED(4,"丧偶"),
;
private int code;
private String msg;
MaritalTypeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.common.demo.pattern.filter;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 性别枚举
* @date 2023/07/11 20:48:02
*/
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.common.demo.pattern.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 测试类
* @date 2023/07/09 14:21:58
*/
public class Test {
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 genderFilter = new GenderFilter(GenderEnum.FEMALE);
List<People> list = genderFilter.doFilter(personList);
System.out.println("女性为:" + list);
// 男性
genderFilter = new GenderFilter(GenderEnum.MALE);
List<People> list1 = genderFilter.doFilter(personList);
System.out.println("男性为:" + list1);
// 男性未婚
genderFilter = new GenderFilter(GenderEnum.MALE);
MaritalTypeFilter maritalTypeFilter = new MaritalTypeFilter(MaritalTypeEnum.UNMARRIED);
List<People> list2 = maritalTypeFilter.doFilter(genderFilter.doFilter(personList));
System.out.println("男性未婚:" + list2);
}
}
测试截图
过滤器模式的特点
优点
- 灵活性:通过定义不同的过滤器实现类和不同的谓词(Predicate),可以灵活地对数据集合进行过滤,可结合多个标准来获取唯一标准,从而得到符合不同条件的子集,其设计概念是支持可插拔设计的。
- 可扩展性:允许开发人员使用不同的标准来过滤一组对象,在实现过滤器模式时,可添加、组合和重用不同的过滤器,从而轻松扩展过滤器的功能。
- 简单性:过滤器模式非常简单且易于理解。它将数据集合和过滤器分开,使得代码更加清晰和易于维护。
- 有序性:过滤器是被设计为一组组的过滤装置,要实现数据过滤,实现对数据顺序性过滤的要求。
- 独立性:每种过滤器必须是独立的实体,其状态不受其它过滤器的影响,每个过滤器都有独立的数据输入输出接口,只要各个过滤器之间传送的数据遵守共同的规约就可以相连接。
缺点
- 性能问题:当数据集合非常大时,过滤器模式可能会导致性能问题。每次过滤都需要遍历整个数据集合,这可能会降低程序的运行效率。
- 配置复杂性:当需要组合多个过滤器时,可能需要编写大量的配置代码,这可能会增加代码的复杂性。
注意事项
- 大数据量时,需要考虑其处理性能。
使用场景
- 需要进行条件过滤的时候,对数据进行特殊处理,处理逻辑与业务逻辑解耦的情况。
- 数据集合的元素需要根据不同的条件进行过滤。例如,我们可能需要从一个商品列表中过滤出价格低于一定值的商品,或者从一个用户列表中过滤出年龄大于一定值的用户。
- 数据集合的元素需要根据不同的条件进行排序。例如,我们可能需要按照价格、销量等因素对商品进行排序,或者按照年龄、性别等因素对用户进行排序。
- 数据集合需要根据多个条件进行复合过滤。例如,我们可能需要从一个商品列表中过滤出价格低于一定值且销量高于一定值的商品,或者从一个用户列表中过滤出年龄大于一定值且性别为男的用户。
- 对于大型数据集合,需要在内存使用方面进行优化。过滤器模式可以帮助我们避免在内存中存储所有数据,而是在需要时逐个元素地处理它们。
更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)