目的:
通过给多个对象一个处理请求的机会,避免请求的发送者和它的接收者耦合。串联接收对象并在链条中传递请求直到一个对象处理它。
它帮助构建一串对象。请求从一个对象中进入并结束然后进入到一个个对象中直到找到合适的处理器。
程序示例:
兽王大声命令他的军队。最近响应的是指挥官,然后是军官,然后是士兵。指挥官,军官,士兵这里就形成了一个责任链。
1.请求类
public class Request{
private final RequestType requestType;
private final String requestDescription;
private boolean handled;
public Request(RequestType requestType, String requestDescription) {
this.requestType = Objects.requireNonNull(requestType);
this.requestDescription = Objects.requireNonNull(requestDescription);
}
public RequestType getRequestType() {
return requestType;
}
public String getRequestDescription() {
return requestDescription;
}
public boolean isHandled() {
return handled;
}
public void markHandled(){
this.handled=true;
}
@Override
public String toString() {
return this.getRequestDescription();
}
}
//请求类型枚举
public enum RequestType{
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
}
2.请求处理器层次结构
//抽象父类
@Slf4j
public abstract class RequestHandler{
private final RequestHandler next;
public RequestHandler(RequestHandler next) {
this.next = next;
}
public void handleRequest(Request request){
if (next!=null){
next.handleRequest(request);
}
}
protected void printHandling(Request request){
log.info("{} handing request \"{}\"",this,request);
}
@Override
public abstract String toString();
}
//指挥官处理类
public class OrcCommander extends RequestHandler{
public OrcCommander(RequestHandler next) {
super(next);
}
@Override
public String toString() {
return "Orc commander";
}
@Override
public void handleRequest(Request request) {
if (request.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
printHandling(request);
request.markHandled();
} else {
super.handleRequest(request);
}
}
}
//军官处理类
public class OrcOfficer extends RequestHandler{
public OrcOfficer(RequestHandler next) {
super(next);
}
@Override
public void handleRequest(Request request) {
if (request.getRequestType().equals(RequestType.TORTURE_PRISONER)) {
printHandling(request);
request.markHandled();
} else
super.handleRequest(request);
}
@Override
public String toString() {
return "Orc Officer";
}
}
//士兵处理类
public class OrcSoldier extends RequestHandler{
public OrcSoldier(RequestHandler next) {
super(next);
}
@Override
public void handleRequest(Request request) {
if (request.getRequestType().equals(RequestType.COLLECT_TAX)) {
printHandling(request);
request.markHandled();
} else
super.handleRequest(request);
}
@Override
public String toString() {
return "Orc Soldier";
}
}
3.下达命令,形成链条
public class OrcKing{
RequestHandler chain;
public OrcKing() {
buildChain();
}
public void buildChain() {
chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
}
public void makeRequest(Request req) {
chain.handleRequest(req);
}
}
4.测试
OrcKing king = new OrcKing();
king.makeRequest(new Request(RequestType.COLLECT_TAX,"collect tax"));
king.makeRequest(new Request(RequestType.TORTURE_PRISONER,"torture prisoner"));
king.makeRequest(new Request(RequestType.DEFEND_CASTLE,"defend castle"));
/*
* Orc Soldier handing request "collect tax"
* Orc Officer handing request "torture prisoner"
* Orc commander handing request "defend castle"
*/
类图:
还可以用接口和流的方式
//处理请求接口
public interface RequestHandler{
boolean canHandlerRequest(Request request);
int getPriority();
void handle(Request request);
String name();
}
//接口实现
@Slf4j
public class OrcCom implements RequestHandler{
@Override
public boolean canHandlerRequest(Request request) {
return request.getRequestType().equals(RequestType.DEFEND_CASTLE);
}
@Override
public int getPriority() {
return 3;
}
@Override
public void handle(Request request) {
request.markHandled();
log.info("{} handing request \"{}\"",name(),request);
}
@Override
public String name() {
return "Orc Commander";
}
}
//....类似
//发号施令
public class OrcKin{
private List<RequestHandler> handlers;
public OrcKin() {
buildChain();
}
private void buildChain() {
handlers = Arrays.asList(new OrcCom(), new OrcOff(), new OrcSol());
}
public void makeRequest(Request request) {
handlers.stream().sorted(Comparator.comparing(RequestHandler::getPriority))
.filter((hander)->hander.canHandlerRequest(request))
.findFirst()
.ifPresent(hander->hander.handle(request));
}
}