责任链模式
概述
《设计模式》一书中对于 “责任链模式” 的意图描述如下:
使多个对象有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止
一般的 UML 结构图如下所示:
其中,Handler
将会包含直接后继处理类 successor
,用于处理后续的更通用请求
一般在以下情况下使用责任链模式:
- 有多个对象可以处理一个请求,哪个对象处理请求由运行时进行确定
- 在不想明确指定接受者的情况下,向多个对象中的一个提交一个请求
- 可处理请求的对象集合应该被动态指定
具体示例
在某些情况下,可能需要对相关的请求参数进行相关的解析,得到在某个通用模块中需要用到的参数,然而,对于不同的请求参数,解析的方式也可能不同,因此我们可以通过使用责任链模式来解决这个问题。
假设我们现在的系统中存在以下的参数类型:
public interface UpdateParam { // 更新数据时的参数类型
String updatedId();
}
public interface DeletedParam { // 删除数据时的参数类型
String deletedId();
}
public interface InsertedParam { // 增加数据时的参数类型
String insertedId();
}
在当前的上下文环境下,这三个接口返回的都是通用模块需要的参数,但是由于这三个参数的使用具体由不同的开发使用,现在已经很难对这几个参数类型进行 “提炼父类” 的重构。并且除了这三个参数类型之外,可能系统中还存在某些其它类型的参数,如 List
、Map
等,对这些类型同样无法使用 “提炼父类” 的操作进行泛化处理。为了能够适配通用模块的需求,我们可以定义如下的处理类 Handler
:
public abstract class AbstractParamHandler {
private final AbstractParamHandler successor;
public AbstractParamHandler(AbstractParamHandler successor) {
this.successor = successor;
}
protected String successorHandler(Object Param) {
return this.successor == null ? null : this.successor.handler(param);
}
// 针对参数对象,对其进行解析以得到对应的通用参数值,如果无法解析,则返回 null
public abstract String handler(Object param);
}
针对上面我们提到的三种参数类型,我们可以定义对应的参数处理类:
public class InsertedParamHandler extends AbstractParamHandler {
public InsertedParamHandler(AbstractParamHandler successor) {
super(successor);
}
@Override
public String handler(Object param) {
if (!(param instanceof InsertedParam)) {
return successorHandler(param);
}
return ((InsertedParam) param).insertedId();
}
}
public class UpdatedParamHandler extends AbstractParamHandler {
public UpdatedParamHandler(AbstractParamHandler successor) {
super(successor);
}
@Override
public String handler(Object param) {
if (!(param instanceof UpdatedParam)) {
return successorHandler(param);
}
return ((UpdatedParam) param).updatedId();
}
}
public class DeletedParamHandler extends AbstractParamHandler {
public DeletedParamHandler(AbstractParamHandler successor) {
super(successor);
}
@Override
public String handler(Object param) {
if (!(param instanceof DeletedParam)) {
return successorHandler(param);
}
return ((DeletedParam) param).deletedId();
}
}
对于客户端来讲,只要适当组织好这些处理类之间的关系即可:
public class Client {
private AbstractParamHandler handler;
public Client() {
// 将这三个处理类组合成处理链
InsertParamHandler h1 = new InsertParamHandler(null);
UpdatedParamHandler h2 = new UpdatedParamHandler(h1);
DeleteParamHandler h3 = new DeletedParamHandler(h2);
this.handler = h3;
}
String handler(Object param) {
return handler.handler(param);
}
}
如果后续发现 List
类型的参数也需要解析,那么只需要再将 DeletedParamHandler
作为它的后继处理即可完成对所有类型的参数解析
总结
针对不同请求的特殊处理,通过责任连模式来选择合适的处理对象,一般这种模式会结合 “组合模式” 一起使用,可以合理的适配每个父组件的特殊处理
参考:
[1] 《设计模式—可复用面向对象基础》