设计模式:责任链设计模式

一、概述

责任链设计模式是一种行为型设计模式,它将请求的发送者和接收者解耦,将多个处理对象连成一条责任链,依次处理请求,直到请求被处理或者到达责任链的末尾。该模式常用于日志记录、权限验证、请求过滤等场景。

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 链式调用方式构建责任链

我们还可以使用链式调用方式构建责任链,这种方式通过在处理对象中返回自身引用,以便在处理请求时依次调用链表中的处理对象。

责任链模式是一种行为型设计模式,它允许多个对象按照一定的顺序依次处理同一个请求,直到其中一个对象处理该请求或者所有对象都无法处理该请求为止。该模式有助于降低请求发送者与接收者之间的耦合度,增强系统的灵活性和可扩展性。

在责任链模式中,我们通常需要实现以下几个角色:

  1. 抽象处理者(Handler):定义处理请求的接口,并保存下一个处理者的引用;
  2. 具体处理者(ConcreteHandler):实现抽象处理者定义的处理请求接口,如果自己能够处理该请求,则处理请求,否则将请求传递给下一个处理者;
  3. 请求(Request):包含需要处理的信息;
  4. 客户端(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.

六、适用场景

责任链模式适用于以下场景:

  1. 处理一个请求的对象集合可以动态配置;
  2. 需要避免请求发送者和接收者之间的耦合关系,或者希望动态指定请求处理者的情况;
  3. 多个对象可以处理同一请求,但是具体哪个对象处理该请求在运行时才能确定;
  4. 在不明确指定接收者的情况下,向多个对象中的一个或几个对象发出请求,而不必显式指定接收者。

七、优缺点

7.1 优点

  1. 降低系统的耦合度:请求发送者和接收者之间的耦合度降低,因为发送者不需要知道请求的处理细节,而只需要知道一个处理请求的对象即可;
  2. 增强系统的灵活性和可扩展性:可以动态地增加或删除处理者,而不需要修改原有的代码;
  3. 简化对象之间的交互:责任链模式可以通过链式调用方式简化对象之间的交互,使得代码更加简洁易懂。

7.2 缺点

  1. 对请求的处理顺序敏感:如果处理者之间的处理顺序发生变化,可能会导致请求的处理结果不正确,因此需要仔细设计责任链的结构;
  2. 可能会导致请求得不到处理:如果责任链没有正确地构建,或者没有设置好处理对象的顺序,可能会导致某些请求得不到处理;
  3. 可能会影响系统性能:责任链模式可能会导致请求需要遍历整个责任链才能得到处理,而且在链较长的情况下可能会影响系统的性能。

 

HTML 15992 字节 1273 单词 547 行

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值