设计模式-过滤器模式

news2024/11/15 19:29:32
设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • Java中的过滤器介绍
    • 代码示例
      • Java实现过滤器模式
      • Python实现过滤器模式
    • 过滤器模式在spring中的应用


模式介绍

过滤器模式是一种设计模式,它允许开发人员使用不同的标准来过滤一组对象。这种模式是通过运算逻辑以解耦的方式将它们联系起来。在结构上,这种类型的设计模式属于结构型模式,即按条件筛选一组对象出来。

过滤器模式的组成部分包括:

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

此外,根据具体的使用场景,还可以扩展出过滤器链(FilterChain)的概念,将多个过滤器按照一定的顺序组合起来,形成一个过滤器链,依次对数据进行过滤。

总的来说,过滤器模式的核心思想是将筛选条件和数据集合分离,使得二者可以独立变化而互不影响。这种模式有助于提高系统的灵活性和可维护性。

在这里插入图片描述

模式特点

过滤器模式的优点包括:

  1. 灵活性:通过定义不同的过滤器实现类和谓词,可以灵活地对数据集合进行过滤,得到符合不同条件的子集。
  2. 可扩展性:可以轻松地添加、组合和重用不同的过滤器,扩展过滤器的功能。
  3. 简单性:将数据集合和过滤器分开,使得代码更加清晰和易于维护。

然而,过滤器模式也存在一些缺点:

  1. 性能问题:当数据集合非常大时,每次过滤都需要遍历整个数据集合,可能导致性能问题。
  2. 配置复杂性:当需要组合多个过滤器时,可能需要编写大量的配置代码,增加了代码的复杂性。

在这里插入图片描述

应用场景

过滤器模式的应用场景主要包括:

  1. 数据过滤:通过过滤器可以实现对数据的清晰化、加密、去重、去重复等处理,有效降低数据处理的时间和成本。
  2. 网络安全:过滤器可以识别一些有害的请求或数据包,对其进行屏蔽或加工,提高网络的安全性。
  3. 性能优化:通过过滤器可以对数据进行压缩、加速、减少不必要的重复等优化处理,提高系统的性能。
  4. 内容控制:过滤器可以识别出恶意或不当的内容,加以过滤或替换,维护良好的内容生态。
  5. 业务逻辑与处理逻辑解耦:当需要对数据进行特殊处理,且处理逻辑与业务逻辑需要解耦时,可以使用过滤器模式。例如,需要对人员进行过滤,同时不想与业务代码耦合。可以定义一个过滤接口DataFilter,并增加其实现类DataFilterByOne、DataFilterByTwo、DataFilterByThree,内部增加过滤逻辑。消费者直接调用具体过滤类即可。

在这里插入图片描述

Java中的过滤器介绍

在Java中,"过滤器"的概念在不同的上下文中有不同的含义。以下是一些常见的情境和相关的Java过滤器概念:

  1. Servlet过滤器(Filter in Servlet API)

    • 在Java Web开发中,Servlet过滤器是一个设计模式,允许你在请求到达Servlet或JSP之前或之后执行某些操作。
    • 过滤器通常用于执行以下任务:
      • 字符编码设置。
      • 日志记录。
      • 认证和授权。
      • 数据压缩。
      • 缓存。
    • 创建一个过滤器,你需要实现javax.servlet.Filter接口,并重写doFilter方法。
  2. Java Stream API中的过滤(Filter in Java Stream API)

    • 在Java 8及以后的版本中,Stream API提供了一个filter方法,用于从原始数据源中筛选出满足特定条件的元素。
    • 例如,你可以使用filter方法来筛选出一个整数列表中的所有偶数。
  3. 自定义注解过滤器(Custom Annotation-based Filters)

    • 在Spring框架中,你可以创建自定义的注解过滤器,这些过滤器可以基于某些条件来决定是否继续处理请求或将其转发给其他组件。
  4. 数据库查询中的过滤(Filter in Database Queries)

    • 在执行数据库查询时,你可能会使用某种形式的"过滤",以只获取你感兴趣的数据。这通常在SQL查询中使用WHERE子句完成。
  5. 第三方库和框架中的过滤器

    • 许多第三方库和框架在它们自己的API中实现了过滤的概念。例如,MyBatis-Plus有一个强大的查询构造器,其中包括过滤条件的功能。
  6. 其他上下文

    • 在不同的框架、库或应用程序中,"过滤器"可能有其特定的用途和实现方式。

如果你有关于特定上下文或技术的具体问题,请提供更多细节,我会为你提供更详细的解答。

在这里插入图片描述

代码示例

Java实现过滤器模式

以下是一个简单的Java实现过滤器模式的示例:

import java.util.ArrayList;
import java.util.List;

// 抽象过滤器角色
interface Filter {
    boolean isAccepted(Object obj);
}

// 具体过滤器角色1
class ConcreteFilter1 implements Filter {
    private String name;

    public ConcreteFilter1(String name) {
        this.name = name;
    }

    @Override
    public boolean isAccepted(Object obj) {
        return ((String) obj).startsWith(name);
    }
}

// 具体过滤器角色2
class ConcreteFilter2 implements Filter {
    private String name;

    public ConcreteFilter2(String name) {
        this.name = name;
    }

    @Override
    public boolean isAccepted(Object obj) {
        return ((String) obj).endsWith(name);
    }
}

// 被过滤的主体角色
class Subject {
    private List<String> items = new ArrayList<>();
    private List<Filter> filters = new ArrayList<>();

    public void addItem(String item) {
        items.add(item);
    }

    public void addFilter(Filter filter) {
        filters.add(filter);
    }

    public List<String> getItems() {
        List<String> result = new ArrayList<>();
        for (String item : items) {
            for (Filter filter : filters) {
                if (filter.isAccepted(item)) {
                    result.add(item);
                    break; // 如果一个item通过了所有filters,那么直接加入到结果集中,不必再继续遍历下去。
                }
            }
        }
        return result;
    }
}

使用示例:

public class Main {
    public static void main(String[] args) {
        Subject subject = new Subject(); // 创建被过滤的主体对象。
        subject.addItem("apple"); // 添加被过滤的主体对象。
        subject.addItem("banana"); // 添加被过滤的主体对象。
        subject.addItem("pear"); // 添加被过滤的主体对象。
        subject.addItem("grape"); // 添加被过滤的主体对象。
        subject.addItem("orange"); // 添加被过滤的主体对象。
        subject.addFilter(new ConcreteFilter1("a")); // 添加第一个具体过滤器对象。只接受以"a"开头的字符串。例如"apple"。此时被过滤的主体对象变为:[apple]。剩余的未通过的字符串:["banana", "pear", "grape", "orange"]。但是这四个对象可以接受其他过滤器的检查。因此它们不会立即被丢弃掉。例如"banana"可以接受第二个过滤器的检查,而"orange"不可以接受任何过滤器的检查。所以最后的筛选结果应该是["apple", "banana"]。因为只有这两个对象通过了所有过滤器的检查。而"pear"和"grape"没有通过所有过滤器的检查,所以最后不应该出现在结果集中。这和之前的理解可能不同,但这确实是被过滤器模式的正确应用方式。只有在当前没有被任何过滤器所接受的剩余字符串不再继续参与后面的过滤过程(也就是不在参与后续的循环),而直接丢弃掉。如果一个字符串通过了所有过滤器的检查,那么它就可以直接加入到结果集中,不必再继续遍历下去。如果一个字符串没有通过所有过滤器的检查,那么它就会一直保持下去,直到不再参与后续的过滤过程为止。因此,如果一个字符串没有通过所有过滤器的检查,那么它就会一直保持下去,直到不再参与后续的过滤过程为止。这是被过滤器模式的正确应用方式。

Python实现过滤器模式

在Python中,过滤器模式可以通过使用生成器函数来实现。生成器函数允许你编写一个函数,该函数在每次调用时生成一个新的值,而不是返回所有值。这种函数特别适合用于过滤器模式,因为你可以根据某些条件来生成或过滤值。

以下是一个Python实现过滤器模式的示例:

def filter_numbers(numbers, condition):
    """
    使用给定条件过滤数字的生成器函数。
    """
    for num in numbers:
        if condition(num):
            yield num

# 示例用法
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = filter_numbers(numbers, lambda x: x % 2 == 0)

# 输出结果
for num in even_numbers:
    print(num)

在这个示例中,filter_numbers函数接受一个数字列表和一个条件函数作为参数。条件函数是一个接受一个参数并返回布尔值的函数。在每次迭代中,如果条件函数对当前数字返回True,则该数字被生成并返回。

你可以根据需要修改条件函数来过滤不同的数字。例如,你可以使用lambda x: x > 5作为条件函数来过滤出大于5的数字。

在这里插入图片描述

过滤器模式在spring中的应用

过滤器模式在Spring框架中有多种应用场景,其中最常见的是在Web应用中用于处理请求和响应的过滤。Spring提供了一些内置的过滤器,例如拦截器和过滤器,你可以通过实现这些过滤器来对请求和响应进行预处理或后处理。

下面是一个使用Spring拦截器的示例:

  1. 创建一个实现HandlerInterceptor接口的类:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在请求处理之前执行的操作
        // 例如,检查请求的权限或身份验证
        return true; // 返回true表示继续处理请求,返回false表示中止请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理之后执行的操作
        // 例如,记录日志或修改响应内容
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在请求处理完成之后执行的操作
        // 例如,清理资源或关闭数据库连接
    }
}
  1. 在Spring配置文件中注册拦截器:
<bean id="myInterceptor" class="com.example.MyInterceptor" />

<bean class="org.springframework.web.servlet.handler.HandlerInterceptorRegistry">
    <property name="interceptors">
        <list>
            <ref bean="myInterceptor" />
        </list>
    </property>
</bean>

通过这种方式,你可以在请求处理之前、之后或完成后执行自定义的逻辑,例如权限检查、日志记录或修改响应内容等。过滤器模式在Spring中的其他应用还包括用于数据转换、验证和格式化的组件。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1339510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL常用命令合集(Mac版)

mysql信息 MySQL位置 which mysql查看版本 mysql --version启动与关闭 使用mysql.server启用脚本来执行&#xff0c;默认在/usr/local/mysql/support-files这个目录中。 启动 sudo /usr/local/mysql/support-files/mysql.server start关闭 sudo /usr/local/mysql/suppor…

JMeter逻辑控制器之ForEach控制器

1. 背景 前段时间在对某项目进行测试&#xff0c;存在一个需要遍历所有组织机构后给每个组织下新增部门的场景&#xff0c;其实也可以通过在数据库中直接添加数据这种方式来实现&#xff0c;但是有点风险&#xff0c;可能会生成脏数据&#xff0c;后期也不好排查&#xff0c;最…

音视频学习(二十二)——rtmp发流(tcp方式)

前言 本文主要介绍自研的RtmpStreamSender.dll&#xff0c;rtmp库提供接口接收裸流数据&#xff0c;支持将裸流数据封装为flv格式并通过rtmp协议发流。 关于rtmp协议基础介绍可查看&#xff1a;https://blog.csdn.net/www_dong/article/details/131026072 关于rtmp收流介绍可…

编程笔记 html5cssjs 004 我的第一个页面

编程笔记 html5&css&js 004 我的第一个页面 一、基本结构二、HTML标签三、HTML元素四、HTML属性五、编写第一个网页六、使用VSCODE小结 开始编写网页&#xff0c;并且使用第一个网页成为一个母板&#xff0c;用于完成后续内容的学习。有一个基本要求&#xff0c;显示结…

errors包返回堆栈信息的性能测试

errors包返回堆栈信息的性能测试 上一篇Golang中使用errors返回调用堆栈信息 讲了使用第三方开源库的errors github.com/go-errors/errors&#xff0c;错误信息带调用栈&#xff0c;方便定位错误的抛出位置。 通过堆栈的信息来定位是方便了&#xff0c;性能怎么样&#xff0c…

docker学习笔记02-安装mysql

1.安装mysql8 下载MySQL镜像 docker pull mysql:8.0创建并启动容器 docker run -itd --name mysqltest -p 9999:3306 -e MYSQL_ROOT_PASSWORD123456 mysql其中-it是交互界面 -d是后台执行 -name 指定容器名称 -p指定映射端口 -e设置环境变量 最后mysql是镜像名或者用镜像id如…

Switch语句与链接—计算机系统基础

实验内容&#xff1a;修改二进制可重定位目标文件“phase1.o”中相关节的内容&#xff08;注意不允许修改.text节和重定位节的内容&#xff09;&#xff0c;使其与main.o模块如下链接后运行时输出目标字符串“123456789” gcc -no-pie -o linkbomb main.o phase1.o ./linkbomb…

Spring Boot+RocketMQ 实现多实例分布式环境下的事件驱动

为什么要使用MQ&#xff1f; 在Spring Boot Event这篇文章中已经通过Guava或者SpringBoot自身的Listener实现了事件驱动&#xff0c;已经做到了对业务的解耦。为什么还要用到MQ来进行业务解耦呢&#xff1f; 首先无论是通过Guava还是Spring Boot自身提供的监听注解来实现的事…

CNN实现对手写字体的迭代

导入库 import torchvision import torch from torchvision.transforms import ToTensor from torch import nn import matplotlib.pyplot as plt 导入手写字体数据 train_dstorchvision.datasets.MNIST(data/,trainTrue,transformToTensor(),downloadTrue) test_dstorchvis…

Hive实战:统计总分与平均分

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、将文本文件上传到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、创建Hive表&#xff0c;加载HDFS数据文件…

websocket 介绍

目录 1&#xff0c;前端如何实现即时通讯短轮询长轮询 2&#xff0c;websocket2.1&#xff0c;握手2.2&#xff0c;握手过程举例2.3&#xff0c;socket.io 3&#xff0c;websocket 对比 http 的优势 1&#xff0c;前端如何实现即时通讯 在 websocket 协议出现之前&#xff0c;…

Tuxera NTFS for Mac2024免费Mac读写软件下载教程

在日常生活中&#xff0c;我们使用Mac时经常会遇到外部设备不能正常使用的情况&#xff0c;如&#xff1a;U盘、硬盘、软盘等等一系列存储设备&#xff0c;而这些设备的格式大多为NTFS&#xff0c;Mac系统对NTFS格式分区存在一定的兼容性问题&#xff0c;不能正常读写。 那么什…

Flask 与微信小程序对接

Flask 与微信小程序的对接 在 web/controllers/api中增建py文件&#xff0c;主要是给微信小程序使用的。 web/controllers/init.py # -*- coding: utf-8 -*- from flask import Blueprint route_api Blueprint( api_page,__name__ )route_api.route("/") def ind…

c++输入输出流和文件操作总结

目录 一、c的输入输出流——> 指的是字节流的数据传送;具有类型安全和可扩展性。 二、流的出入路径 三、c流类库 ①概览 ②标准输出流&#xff1a; ③标准输入流&#xff1a; 四、文件操作&#xff08;ascii文件和二进制文件&#xff09; 五、字符串流&#xff08;或称…

Amazon CodeWhisperer 免费 AI 代码生成助手体验分享

今年上半年&#xff0c;亚马逊云科技正式推出了实时AI编程助手 Amazon CodeWhisperer&#xff0c;还提供了供所有开发人员免费使用的个人版版本。经过一段时间的体验&#xff0c;我觉得 CodeWhisperer 可以处理编程工作中遇到的很多问题&#xff0c;并且帮助开发人员提高编程效…

opencv和gdal的读写图片波段顺序问题

最近处理遥感影像总是不时听到 图片的波段错了&#xff0c;一开始不明就里&#xff0c;都是图片怎么就判断错了。 1、图像RGB波段顺序判断 后面和大家交流&#xff0c;基本上知道了一个判断标准。 一般来说&#xff0c;进入人眼的自然画面在计算机视觉中一般是rgb波段顺序表示…

【Java EE初阶三 】线程的状态与安全(上)

1. join方法与多线程 1.1 初识多线程 为了提高cpu得利用率&#xff0c;因此就引入了多个线程的概念&#xff1b;即每个线程负责完成整个程序的一部分工作即可。 写一个代码&#xff0c;让主线程&#xff0c;创建一个新的线程&#xff0c;由新线程负责完成运算&#xff08;12。…

Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)

Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存&#xff08;C&#xff09; Baumer工业相机Baumer工业相机通过SDK实现Raw格式的图像保存的技术背景通过SDK获取相机信息的代码分析Baumer工业相机回调函数里保存原始图像数据Baumer保存Raw图像格式重要核心代…

时尚男童穿搭 I 棒球服穿搭永不过时

华棉刷毛复合牛奶丝面料 优质的华棉材质&#xff0c;轻柔中带着韧劲拥有卓越的软糯触感 平整的布面复合细腻的绒毛&#xff0c;增加挺阔感基础的佰搭款&#xff0c;利用率真的高 因为版型宽松&#xff0c;不挑身材&#xff0c;怎么搭都好看绣花是hen时尚的字母类绣花 韩范十…

用编程解决习题【计算机图像处理】

用编程解决习题【计算机图像处理】 前言版权第三章 03采样量化与像素间关系三种距离计算编程 第六章 06图像的直方图变换均衡化直方图编程规定化直方图编程 第七章 07图像的噪声抑制均值滤波 中值滤波计算编程knn滤波计算编程 第十章 10二值图像的分析贴标签 膨胀 腐蚀编程 最后…