请求的预处理和后处理是指在该请求的核心处理之前和之后采取的操作。其中一些操作决定处理是否会继续,而另一些操作则将传入或传出的数据流处理为适合进一步处理的形式。
经典的解决方案包括一系列条件检查,任何失败的检查都会中止请求。嵌套的 if/else 语句是一种标准策略,但这种解决方案会导致代码脆弱性和复制粘贴式编程风格,因为过滤器的流程和过滤器的操作被编译到应用程序中。
以灵活不显眼的方式解决这个问题的关键是要有一个简单的添加和删除处理组件的机制,其中每个组件完成一个特定的过滤动作。
UML 图拦截过滤器模式
设计组件
- 过滤器管理器:过滤器管理器管理过滤器处理。它以正确的顺序使用适当的过滤器创建 FilterChain,并启动处理。
- FilterChain : FilterChain 是独立过滤器的有序集合。
- FilterOne、FilterTwo :这些是映射到目标的单个过滤器。 FilterChain 协调它们的处理。
- Target : Target 是客户端请求的资源。
让我们看一个拦截过滤器模式的例子。
// Java program to illustrate
// Intercepting Filter Pattern
import java.util.ArrayList;
import java.util.List;
interface Filter
{
public void execute(String request);
}
class AuthenticationFilter implements Filter
{
public void execute(String request)
{
System.out.println("Authenticating : " + request);
}
}
class DebugFilter implements Filter
{
public void execute(String request)
{
System.out.println("Log: " + request);
}
}
class Target
{
public void execute(String request)
{
System.out.println("Executing : " + request);
}
}
class FilterChain
{
private List filters = new ArrayList();
private Target target;
public void addFilter(Filter filter)
{
filters.add(filter);
}
public void execute(String request)
{
for (Filter filter : filters)
{
filter.execute(request);
}
target.execute(request);
}
public void setTarget(Target target)
{
this.target = target;
}
}
class FilterManager
{
FilterChain filterChain;
public FilterManager(Target target)
{
filterChain = new FilterChain();
filterChain.setTarget(target);
}
public void setFilter(Filter filter)
{
filterChain.addFilter(filter);
}
public void filterRequest(String request)
{
filterChain.execute(request);
}
}
class Client
{
FilterManager filterManager;
public void setFilterManager(FilterManager filterManager)
{
this.filterManager = filterManager;
}
public void sendRequest(String request)
{
filterManager.filterRequest(request);
}
}
class InterceptingFilter
{
public static void main(String[] args)
{
FilterManager filterManager = new FilterManager(new Target());
filterManager.setFilter(new AuthenticationFilter());
filterManager.setFilter(new DebugFilter());
Client client = new Client();
client.setFilterManager(filterManager);
client.sendRequest("Downloads");
}
}
输出:
Authenticating : Downloads
Log: Downloads
Executing : Downloads
好处 :
- 提高可重用性:公共代码集中在可插拔组件中,增强了重用性。
- 增加灵活性:可以声明性地应用和删除通用通用组件,从而提高灵活性。
缺点:
- 信息共享在拦截模式中效率低下。