一、概述
责任链设计模式是一种行为型设计模式,它将请求的发送者和接收者解耦,将多个处理对象连成一条责任链,依次处理请求,直到请求被处理或者到达责任链的末尾。该模式常用于日志记录、权限验证、请求过滤等场景。
1.1 定义
责任链模式定义了一种处理请求的方式,它让多个处理对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。
1.2 应用场景
责任链模式适用于以下场景:
- 处理对象不确定,需要动态指定处理对象。
- 多个处理对象可以处理同一个请求,但处理对象的顺序可能不同。
- 处理对象的数量和顺序可以动态变化。
1.3 优缺点
责任链模式的优点包括:
- 降低了对象之间的耦合度,提高了代码的灵活性和可扩展性。
- 可以动态地增加或删除处理对象,方便了系统的维护和升级。
- 可以对请求进行灵活的处理,提高了系统的可用性和性能。
责任链模式的缺点包括:
- 可能存在请求不能被处理的情况,需要在责任链的末端添加默认处理对象。
- 系统性能受到责任链长度和处理对象数量的影响。
二、角色介绍
责任链模式包含以下角色:
2.1 抽象处理者(Handler)
抽象处理者定义了一个处理请求的接口,并保存下一个处理对象的引用。它可以是抽象类或接口。
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(Request request);
}
2.2 具体处理者(ConcreteHandler)
具体处理者实现了抽象处理者的接口,并处理它所负责的请求。如果不能处理该请求,则将请求传递给下一个处理对象。
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
// 处理请求
} else {
// 无法处理该请求,将请求传递给下一个处理对象
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
// 如果没有下一个处理对象,则输出日志
System.out.println("No handler available for request.");
}
}
}
}
2.3 客户端(Client)
客户端创建请求对象,并将其发送给第一个处理对象。客户端可以根据需要自定义处理对象的顺序,也可以动态地增加或删除处理对象。
public class Client {
public static void main(String[] args) {
// 创建请求对象
Request request = new Request(RequestType.TYPE_A, "Request A");
// 创建处理对象
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
// 构建责任链
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请求
handlerA.handleRequest(request);
}
}
三、实现步骤
实现责任链模式的步骤如下:
3.1 定义抽象处理者接口
首先,我们需要定义一个抽象处理者接口,该接口包含一个处理请求的方法和一个设置下一个处理对象的方法。
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(Request request);
}
3.2 定义具体处理者类
接着,我们需要定义具体的处理者类,这些类实现了抽象处理者接口,并根据具体的业务需求处理请求。如果当前处理对象无法处理该请求,则将请求传递给下一个处理对象。
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
// 处理请求
} else {
// 无法处理该请求,将请求传递给下一个处理对象
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
// 如果没有下一个处理对象,则输出日志
System.out.println("No handler available for request.");
}
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(Requestrequest) {
if (request.getType() == RequestType.TYPE_B) {
// 处理请求
} else {
// 无法处理该请求,将请求传递给下一个处理对象
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
// 如果没有下一个处理对象,则输出日志
System.out.println("No handler available for request.");
}
}
}
}
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_C) {
// 处理请求
} else {
// 无法处理该请求,将请求传递给下一个处理对象
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
// 如果没有下一个处理对象,则输出日志
System.out.println("No handler available for request.");
}
}
}
}
3.3 构建责任链
接下来,我们需要将具体处理者对象连成一条责任链,以便依次处理请求。可以在客户端中手动设置处理对象的顺序,也可以使用链表、静态链表或线程池方式动态构建责任链。
Handler链的构建方式可以有多种,下面分别介绍链表、静态链表和线程池方式。
链表方式构建责任链:
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
静态链表方式构建责任链:
Handler[] handlers = new Handler[] {
new ConcreteHandlerA(),
new ConcreteHandlerB(),
new ConcreteHandlerC()
};
for (int i = 0; i < handlers.length - 1; i++) {
handlers[i].setNextHandler(handlers[i + 1]);
}
线程池方式构建责任链:
Executor executor = Executors.newFixedThreadPool(3);
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
executor.execute(handlerA);
3.4 客户端调用
最后,我们需要创建一个请求对象,并将其发送给第一个处理对象。客户端可以根据需要自定义处理对象的顺序,也可以动态地增加或删除处理对象。
public class Client {
public static void main(String[] args) {
// 创建请求对象
Request requestA = new Request(RequestType.TYPE_A, "Request A");
Request requestB = new Request(RequestType.TYPE_B, "Request B");
// 创建处理对象
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
// 构建责任链
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请求
handlerA.handleRequest(requestA);
handlerA.handleRequest(requestB);
}
}
四、代码示例
下面是一个完整的责任链模式的代码示例:
4.1 抽象处理者接口
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(Request request);
}
4.2 具体处理者类
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
System.out.println("Handled by ConcreteHandlerA: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_B) {
System.out.println("Handled by ConcreteHandlerB: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_C) {
System.out.println("Handled by ConcreteHandlerC: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
4.3 构建责任链
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
HandlerC = new ConcreteHandlerC();
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
4.4 客户端调用
public class Client {
public static void main(String[] args) {
// 创建请求对象
Request requestA = new Request(RequestType.TYPE_A, "Request A");
Request requestB = new Request(RequestType.TYPE_B, "Request B");
Request requestC = new Request(RequestType.TYPE_C, "Request C");
Request requestD = new Request(RequestType.TYPE_D, "Request D");
// 创建处理对象
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
// 构建责任链
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请求
handlerA.handleRequest(requestA);
handlerA.handleRequest(requestB);
handlerA.handleRequest(requestC);
handlerA.handleRequest(requestD);
}
}
输出结果如下:
Handled by ConcreteHandlerA: Request A
Handled by ConcreteHandlerB: Request B
Handled by ConcreteHandlerC: Request C
No handler available for request.
五、优化方案
5.1 链表方式构建责任链
在实现责任链模式时,我们可以使用链表方式构建责任链,以便动态添加或删除处理对象。具体方式是将处理对象保存在链表中,并在处理请求时依次调用链表中的处理对象。
public class HandlerChain {
private List<Handler> handlers = new ArrayList<>();
public void addHandler(Handler handler) {
handlers.add(handler);
}
public void handleRequest(Request request) {
for (Handler handler : handlers) {
if (handler.handleRequest(request)) {
break;
}
}
}
}
在上述代码中,我们创建了一个HandlerChain类,它包含一个处理对象列表handlers,可以动态添加或删除处理对象。handleRequest方法遍历handlers列表中的处理对象,并调用它们的handleRequest方法,如果其中一个处理对象能够处理该请求,则返回true,表示请求已被处理,否则继续遍历直到所有的处理对象都无法处理该请求。
5.2 静态链表方式构建责任链
我们也可以使用静态链表方式构建责任链,这种方式通过在处理对象中保存下一个处理对象的引用,以便在处理请求时依次调用链表中的处理对象。
public abstract classHandler {
protected Handler nextHandler;
public Handler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract boolean handleRequest(Request request);
}
public class ConcreteHandlerA extends Handler {
public ConcreteHandlerA(Handler nextHandler) {
super(nextHandler);
}
@Override
public boolean handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
System.out.println("Handled by ConcreteHandlerA: " + request.getContent());
return true;
} else {
if (nextHandler != null) {
return nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
return false;
}
}
}
}
public class ConcreteHandlerB extends Handler {
public ConcreteHandlerB(Handler nextHandler) {
super(nextHandler);
}
@Override
public boolean handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_B) {
System.out.println("Handled by ConcreteHandlerB: " + request.getContent());
return true;
} else {
if (nextHandler != null) {
return nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
return false;
}
}
}
}
public class ConcreteHandlerC extends Handler {
public ConcreteHandlerC(Handler nextHandler) {
super(nextHandler);
}
@Override
public boolean handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_C) {
System.out.println("Handled by ConcreteHandlerC: " + request.getContent());
return true;
} else {
if (nextHandler != null) {
return nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
return false;
}
}
}
}
在上述代码中,我们创建了一个Handler抽象类,它包含一个nextHandler属性,用于保存下一个处理对象的引用。ConcreteHandlerA、ConcreteHandlerB、ConcreteHandlerC类继承自Handler类,并在构造函数中初始化nextHandler属性。handleRequest方法首先判断是否能够处理该请求,如果能够处理,则处理请求并返回true,否则调用下一个处理对象的handleRequest方法处理该请求,如果下一个处理对象为null,则表示没有处理对象能够处理该请求,返回false。
5.3 链式调用方式构建责任链
我们还可以使用链式调用方式构建责任链,这种方式通过在处理对象中返回自身引用,以便在处理请求时依次调用链表中的处理对象。
责任链模式是一种行为型设计模式,它允许多个对象按照一定的顺序依次处理同一个请求,直到其中一个对象处理该请求或者所有对象都无法处理该请求为止。该模式有助于降低请求发送者与接收者之间的耦合度,增强系统的灵活性和可扩展性。
在责任链模式中,我们通常需要实现以下几个角色:
- 抽象处理者(Handler):定义处理请求的接口,并保存下一个处理者的引用;
- 具体处理者(ConcreteHandler):实现抽象处理者定义的处理请求接口,如果自己能够处理该请求,则处理请求,否则将请求传递给下一个处理者;
- 请求(Request):包含需要处理的信息;
- 客户端(Client):创建请求对象,并将其发送给第一个处理者。
下面是一个简单的责任链模式的实现例子:
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
public abstract void handleRequest(Request request);
}
在上述代码中,我们定义了一个Handler抽象类,它包含一个nextHandler属性,用于保存下一个处理对象的引用。setNextHandler方法用于设置下一个处理对象。handleRequest方法定义了处理请求的接口,具体的处理逻辑由子类实现。
定义请求类
public class Request {
private RequestType type;
private String content;
public Request(RequestType type, String content) {
this.type = type;
this.content = content;
}
public RequestType getType() {
return type;
}
public String getContent() {
return content;
}
}
在上述代码中,我们定义了一个Request类,它包含了需要处理的信息,包括请求类型和请求内容。
定义具体处理者类
public class HandlerA extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
System.out.println("Handled by HandlerA: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
public class HandlerB extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_B) {
System.out.println("Handled by HandlerB: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
public class HandlerC extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_C) {
System.out.println("Handled by HandlerC: " + request.getContent());
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for request.");
}
}
}
}
在上述代码中,我们创建了三个具体处理者类HandlerA、HandlerB、HandlerC,它们分别处理请求类型为TYPE_A、TYPE_B、TYPE_C的请求。如果自己能够处理该请求,则处理请求;否则将请求传递给下一个处理者处理。
构建责任链
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
Handler handlerC = new HandlerC();
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
在上述代码中,我们创建了三个处理者对象handlerA、handlerB、handlerC,并按照顺序构建了责任链,将它们连接起来。
客户端调用
public class Client {
public static void main(String[] args) {
// 创建请求对象
Request requestA = new Request(RequestType.TYPE_A, "Request A");
Request requestB = new Request(RequestType.TYPE_B, "Request B");
Request requestC = new Request(RequestType.TYPE_C, "Request C");
Request requestD = new Request(RequestType.TYPE_D, "Request D");
// 创建处理对象
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
Handler handlerC = new HandlerC();
// 构建责任链
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请求
handlerA.handleRequest(requestA);
handlerA.handleRequest(requestB);
handlerA.handleRequest(requestC);
handlerA.handleRequest(requestD);
}
}
在上述代码中,我们创建了四个请求对象requestA、requestB、requestC、requestD,并创建了三个处理对象handlerA、handlerB、handlerC。然后构建了责任链,并将请求发送给第一个处理对象handlerA。输出结果如下:
Handled by HandlerA: Request A
Handled by HandlerB: Request B
Handled by HandlerC: Request C
No handler available for request.
六、适用场景
责任链模式适用于以下场景:
- 处理一个请求的对象集合可以动态配置;
- 需要避免请求发送者和接收者之间的耦合关系,或者希望动态指定请求处理者的情况;
- 多个对象可以处理同一请求,但是具体哪个对象处理该请求在运行时才能确定;
- 在不明确指定接收者的情况下,向多个对象中的一个或几个对象发出请求,而不必显式指定接收者。
七、优缺点
7.1 优点
- 降低系统的耦合度:请求发送者和接收者之间的耦合度降低,因为发送者不需要知道请求的处理细节,而只需要知道一个处理请求的对象即可;
- 增强系统的灵活性和可扩展性:可以动态地增加或删除处理者,而不需要修改原有的代码;
- 简化对象之间的交互:责任链模式可以通过链式调用方式简化对象之间的交互,使得代码更加简洁易懂。
7.2 缺点
- 对请求的处理顺序敏感:如果处理者之间的处理顺序发生变化,可能会导致请求的处理结果不正确,因此需要仔细设计责任链的结构;
- 可能会导致请求得不到处理:如果责任链没有正确地构建,或者没有设置好处理对象的顺序,可能会导致某些请求得不到处理;
- 可能会影响系统性能:责任链模式可能会导致请求需要遍历整个责任链才能得到处理,而且在链较长的情况下可能会影响系统的性能。
文章评论