设计模式--过滤器模式

655 阅读4分钟

一、什么是过滤器模式

过滤器模式(Filter Pattern)又称标准模式(Criteria Pattern)是一种设计模式,属于结构型模式。这种模式允许开发人员使用不同的标准来过滤一组对象,通过运算逻辑以解耦的方式将它们连接起来。过滤器模式可结合多个标准来获得单一标准。说白了,就是按条件筛选一组对象出来。

二、过滤器模式的实现

2.1 过滤器模式角色

    1. 抽象过滤器角色(AbstractFilter) :负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
    1. 具体过滤器角色(ConcreteFilter) :该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
    1. 被过滤的主体角色(Subject) :一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。

2.2 过滤器模式类图

image.png

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);
    }
}

image.png

三、过滤器模式的特点

3.1 优点

  • 灵活性:通过定义不同的过滤器实现类和不同的谓词(Predicate),可以灵活地对数据集合进行过滤,可结合多个标准来获取唯一标准,从而得到符合不同条件的子集,其设计概念是支持可插拔设计的。

  • 可扩展性:允许开发人员使用不同的标准来过滤一组对象,在实现过滤器模式时,可添加、组合和重用不同的过滤器,从而轻松扩展过滤器的功能

  • 简单性:过滤器模式非常简单且易于理解。它将数据集合和过滤器分开,使得代码更加清晰和易于维护

  • 有序性:过滤器是被设计为一组组的过滤装置,要实现数据过滤,实现对数据顺序性过滤的要求。

  • 独立性:每种过滤器必须是独立的实体,其状态不受其它过滤器的影响,每个过滤器都有独立的数据输入输出接口,只要各个过滤器之间传送的数据遵守共同的规约就可以相连接。

3.2 缺点

  • 性能问题:当数据集合非常大时,过滤器模式可能会导致性能问题。每次过滤都需要遍历整个数据集合,这可能会降低程序的运行效率

  • 配置复杂性:当需要组合多个过滤器时,可能需要编写大量的配置代码,这可能会增加代码的复杂性。

3.3 注意事项

大数据量时,需要考虑其处理性能