一、过滤器模式
概述
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准
主要解决:在众多数据中,根据特定的标准,在一组数据中筛选出不同标准的数据
优缺点
优点:
- 将对象的过滤、校验逻辑抽离出来,降低系统的复杂度
- 过滤规则可实现重复利用
缺点:
- 性能较低,每个过滤器对每一个元素都会进行遍历。如果有n个元素,m个过滤器,则时间复杂度为O(mn)
1. 各个角色介绍
1.1 过滤器接口(Filter)
- 定义了过滤器的基本方法,具体的实现还要具体过滤器角色去参与,在实际应用中可以扩展该接口以适应不同的过滤条件
1.2 具体命过滤器(ConcreteFilter)
- 实现了过滤器接口,负责执行具体的过滤操作。对数据进行过滤
1.3 过滤链(FilterChain)
-
将多个过滤器按照一定的顺序组合起来,形成一个过滤器链,依次对数据进行过滤
2. UML图
首先创建一个 Shape 对象,作为过滤的接口 IFilter,然后实现该接口,创建对应的 CornerFilter、CurveFilter、EdgeFilter具体过滤器。然后创建带有过滤器的过滤链 FilterChain,基于各种标准和它们的结合来过滤 Shape 对象的列表
3. 具体例子和代码
角色分配
- Shape:形状
- IFilter:过滤器接口
- CornerFilter:角过滤器(实现过滤器接口)
- EdgeFilter:边过滤器(实现过滤器接口)
- CurveFilter:曲线过滤器(实现过滤器接口)
- FilterChain:过滤链
3.1 形状
- Instruction
package com.vinjcent.prototype.filter;
import io.swagger.annotations.ApiModelProperty;
/**
* @author vinjcent
* @description 形状
*/
public class Shape {
@ApiModelProperty("形状名称")
private String name;
@ApiModelProperty("是否有角")
private Boolean isCorner;
@ApiModelProperty("边数")
private Integer edges;
@ApiModelProperty("线构成类型")
private String type;
public Shape(String name, Boolean isCorner, Integer edges, String type) {
this.name = name;
this.isCorner = isCorner;
this.edges = edges;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getCorner() {
return isCorner;
}
public void setCorner(Boolean corner) {
isCorner = corner;
}
public Integer getEdges() {
return edges;
}
public void setEdges(Integer edges) {
this.edges = edges;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
3.2 过滤接口及其实现类
- IFilter
package com.vinjcent.prototype.filter;
import java.util.List;
/**
* @author vinjcent
* @description 过滤接口
*/
public interface IFilter {
/**
* 适配标准形状
*
* @param shapes 形状列表
* @return 适配的形状列表
*/
List<Shape> adaptFilter(List<Shape> shapes);
}
- CornerFilter
package com.vinjcent.prototype.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author vinjcent
* /
* @description 角过滤器
*/
public class CornerFilter implements IFilter {
@Override
public List<Shape> adaptFilter(List<Shape> shapes) {
// 符合具有角的形状
List<Shape> cornerFilter = new ArrayList<>();
for (Shape shape : shapes) {
if (shape.getIsCorner()) {
cornerFilter.add(shape);
}
}
return cornerFilter;
}
}
- EdgeFilter
package com.vinjcent.prototype.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author vinjcent
* /
* @description 边过滤器
*/
public class EdgeFilter implements IFilter {
@Override
public List<Shape> adaptFilter(List<Shape> shapes) {
// 边数大于0的形状
List<Shape> edgeFilter = new ArrayList<>();
for (Shape shape : shapes) {
if (shape.getEdges() > 0) {
edgeFilter.add(shape);
}
}
return edgeFilter;
}
}
- CurveFilter
package com.vinjcent.prototype.filter;
import java.util.ArrayList;
import java.util.List;
/**
* @author vinjcent
* /
* @description 曲线过滤器
*/
public class CurveFilter implements IFilter {
@Override
public List<Shape> adaptFilter(List<Shape> shapes) {
// 曲线
List<Shape> curveFilter = new ArrayList<>();
for (Shape shape : shapes) {
if (shape.getType().toLowerCase().contains("curve")) {
curveFilter.add(shape);
}
}
return curveFilter;
}
}
3.3 过滤链
- FilterChain
package com.vinjcent.prototype.filter;
import com.vinjcent.api.utils.CollectionUtils;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author vinjcent
* @description 过滤链
*/
@Data
public class FilterChain {
@ApiModelProperty("过滤器集合")
private List<IFilter> filters;
public FilterChain(List<IFilter> filters) {
this.filters = filters;
}
public List<Shape> doFilter(List<Shape> shapes) {
if (CollectionUtils.isEmpty(filters) || CollectionUtils.isEmpty(shapes)) {
return new ArrayList<>();
}
List<Shape> afterFilterShapes = new ArrayList<>(shapes);
// 执行过滤
for (IFilter filter : filters) {
afterFilterShapes = filter.adaptFilter(afterFilterShapes);
}
return afterFilterShapes;
}
}
3.4 测试主函数
package com.vinjcent.prototype.filter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author vinjcent
* 过滤模式
*/
public class Main {
public static void main(String[] args) {
List<Shape> shapes = new ArrayList<>();
shapes.add(new Shape("Circle", false, 0, "Curve"));
shapes.add(new Shape("Triangle", true, 3, "Straight"));
shapes.add(new Shape("Rectangle", true, 4, "Straight"));
shapes.add(new Shape("Square", true, 4, "Straight"));
shapes.add(new Shape("Oval", false, 0, "Curve"));
shapes.add(new Shape("Sector", true, 2, "Curve and Straight"));
CornerFilter cornerFilter = new CornerFilter();
EdgeFilter edgeFilter = new EdgeFilter();
CurveFilter curveFilter = new CurveFilter();
// 具有角、边的形状
FilterChain cornerAndEdgeFilterChain = new FilterChain(Arrays.asList(cornerFilter, edgeFilter));
List<Shape> cornerAndEdgeShapes = cornerAndEdgeFilterChain.doFilter(shapes);
System.out.println("具有角、边的形状:");
printResult(cornerAndEdgeShapes);
// 具有角、曲线的形状
FilterChain cornerAndCurveFilterChain = new FilterChain(Arrays.asList(cornerFilter, curveFilter));
List<Shape> cornerAndCurveShapes = cornerAndCurveFilterChain.doFilter(shapes);
System.out.println("\n具有角、曲线的形状:");
printResult(cornerAndCurveShapes);
// 具有边、曲线的形状
FilterChain edgeAndCurveFilterChain = new FilterChain(Arrays.asList(edgeFilter, curveFilter));
List<Shape> edgeAndCurveShapes = edgeAndCurveFilterChain.doFilter(shapes);
System.out.println("\n具有边、曲线的形状:");
printResult(edgeAndCurveShapes);
}
public static void printResult(List<Shape> shapes) {
for (Shape shape : shapes) {
System.out.println("Shape{" +
"name='" + shape.getName() + '\'' +
", isCorner=" + shape.getIsCorner() +
", edges=" + shape.getEdges() +
", type='" + shape.getType() + '\'' +
'}');
}
}
}
- 测试结果
4. 使用场景
- 在某些场合,比如要对数据进行过滤,不仅仅局限于一个标准的情况下,进行分组,例如:数据查询、日志过滤、请求过滤