设计模式——责任链模式

本文介绍了设计模式中的责任链模式,阐述了其在Java Web中Filter的典型应用。通过实例展示了如何简单实现责任链模式,包括字母、数字和空格的过滤。同时,讨论了现有实现存在的问题,如处理器顺序不可配置、耦合度过高等,并提出了通过类似FilterChain的改进方案以降低耦合度,加深了对责任链模式工作原理的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说到“各司其职”,我们首先想到的是工厂里的流水线,这是标准的各司其职,而且有助于提高效率,但是在设计模式中的各司其职就要说到责任链模式,从名称上来看已经非常清晰,就是把一件工作分别经过链上的各个节点,让这些节点依次处理这个工作。关于这种设计模式的使用,在Java Web中的Filter中是最明显的。

1.关于责任链模式的理解

其实关于这个设计模式具体的理解还是要看我们业务需求,通常来说有以下两种理解:

  • 一个就是如上所说,责任链中的每个节点都负责一部分工作,互相之前各不相同,各司其职,然后共同完成一项工作,
    在处理器中具体的实现方式就是当处理器自己的工作完成之后还要负责调用后面的处理器完成下面的工作Filter就是这种方式,使用FilterChain来完成往下传递请求的任务;
  • 另外一个是,类似于游戏过关的方式,责任链就类似于请求闯关要经过的路程,如果在第一关就挂了,你是到不了第二关的,而在处理器中具体的实现方式就是当在前面处理器已经完成工作了,该请求也不会传递到第二个处理器

2.简单实现责任链模式

下面我们实现一下具体的请求经过责任链的过程,使用第一种理解,我们要做的是过滤一个字符串中的字母、数字和空格:

首先一个通用的处理器Handler:

public abstract class Handler {
        private Handler successor;

        public Handler getSuccessor() {
            return successor;
        }

        public void setSuccessor(Handler successor) {
            this.successor = successor;
        }

        public void handleRequest(String message){}
    }

对应的两个处理器声明如下:

WordHandler负责处理字母和数字:

public class WordHandler extends  Handler{
        @Override
        public void handleRequest(String message) {

            Objects.requireNonNull(message, "message is null in WordHandler");
            Pattern pattern = Pattern.compile("\\w*");
            Matcher matcher = pattern.matcher(message);
            String handledMessage = matcher.replaceAll("");
            System.out.println("in WordHandler, handledMessage:" + handledMessage);

            if(getSuccessor() != null){
                getSuccessor().handleRequest(handledMessage);
            }
        }
    }

SpaceHandler负责处理空格:

public class SpaceHandler extends Handler {
        @Override
        public void handleRequest(String message) {
            Objects.requireNonNull(message, "message is null in SpaceHandler");

            Pattern pattern = Pattern.compile("\\s*");
            Matcher matcher = pattern.matcher(message);
            String handledMessage = matcher.replaceAll("");
            System.out.println("in SpaceHandler, handledMessage:" + handledMessage);

            if(getSuccessor() != null){
                getSuccessor().handleRequest(handledMessage);
            }
        }
    }

在main方法里调用:

public static void main( String[] args ){
        Handler handler1 = new WordHandler();
        Handler handler2 = new SpaceHandler();

        handler1.setSuccessor(handler2);
        handler1.handleRequest("1231sdhff  %*^3kihk 443wr23$%");
    }

结果显示如下:

1.1.png

3.简单责任链模式的问题以及改进

但是在上面的实现过程中有几个问题暴露出来:

  • 处理器Handler之间的执行顺序不能任意配置,只能通过Handler存储它的继承者来实现链表的数据结构才能完成请求的传递;
  • 处理器之间通过设置继承者而关系高度耦合,不利于责任链中处理器的随意添加和删除;

如果想到工厂里的流水线,那么上面的两个问题就很好解决,类比一下请求就是一件产品,责任链就是生产线上的每个工作人员串联起来共同构成,每个工人就是责任链的一个节点,从实际来看,当一个工人对一个产品处理完之后还会管它被传递到哪吗?当然不会,那么谁会管传递的工作?答案是传送带!!bingo!!

在Filter中做类似传送带工作的就是FilterChain,下面我们就模拟一下这个过程!

首先先建立一个HandlerChain的接口:

public interface HandlerChain {
        public void handleRequest(String message);
        public void registerHandler(Handler handler);
    }

和它的实现类如下:

public class ApplicationHandlerChain implements HandlerChain {

        private Map<Integer, Handler> handlers = new HashMap<Integer, Handler>();
        private Integer position = 1;

        public void handleRequest(String message) {
            position++;
            if(position < handlers.size()+1){
                handlers.get(position).handleRequest(message);
            }
        }

        public void registerHandler(Handler handler) {
            if(handler != null){
                if(handler.getClass().isAnnotationPresent(Order.class)){
                    handlers.put(handler.getClass().getAnnotation(Order.class).value(), handler);
                }
            }
        }
    }

和一个标识执行顺序的注解Order如下:

@Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Order {
        int value();
    }

而之前用过的Handler以及实现类如下:

Handler如下:

public abstract class Handler implements Comparable<Handler> {
        public void handleRequest(String message){}
    }

WordHandler如下:

@Order(2)
public class WordHandler extends Handler{
    private HandlerChain chain;

    public WordHandler(HandlerChain chain){
        this.chain = chain;
    }

    @Override
    public void handleRequest(String message) {
        Objects.requireNonNull(message, "message is null in WordHandler");
        Pattern pattern = Pattern.compile("\\w*");
        Matcher matcher = pattern.matcher(message);
        String handledMessage = matcher.replaceAll("");
        System.out.println("in WordHandler, handledMessage:" + handledMessage);

        chain.handleRequest(handledMessage);
    }

    public int compareTo(Handler handler) {
        return this.getClass().getAnnotation(Order.class).value() - handler.getClass().getAnnotation(Order.class).value();
    }
}

SpaceHandler如下:

@Order(1)
public class SpaceHandler extends Handler {
    private HandlerChain chain;

    public SpaceHandler(HandlerChain chain){
        this.chain = chain;
    }
    @Override
    public void handleRequest(String message) {
        Objects.requireNonNull(message, "message is null in SpaceHandler");

        Pattern pattern = Pattern.compile("\\s*");
        Matcher matcher = pattern.matcher(message);
        String handledMessage = matcher.replaceAll("");
        System.out.println("in SpaceHandler, handledMessage:" + handledMessage);
        chain.handleRequest(handledMessage);
    }

    public int compareTo(Handler handler) {
        return this.getClass().getAnnotation(Order.class).value() - handler.getClass().getAnnotation(Order.class).value();
    }
}

为了使效果更明显新增一个Handler如下:

@Order(3)
public class SuffixHandler extends Handler {
    private HandlerChain chain;

    public SuffixHandler(HandlerChain chain){
        this.chain = chain;
    }

    @Override
    public void handleRequest(String message) {
        Objects.requireNonNull(message, "message is null in SuffixHandler");
        String handledMessage = message + "@___@";
        System.out.println("in SuffixHandler, handledMessage:" + handledMessage);

        chain.handleRequest(handledMessage);
    }

    public int compareTo(Handler handler) {
        return this.getClass().getAnnotation(Order.class).value() - handler.getClass().getAnnotation(Order.class).value();
    }
}

在main中调用如下:

public static void main( String[] args ){
        HandlerChain chain = new ApplicationHandlerChain();
        Handler handler1 = new WordHandler(chain);
        Handler handler2 = new SuffixHandler(chain);
        Handler handler3 = new SpaceHandler(chain);

        chain.registerHandler(handler1);
        chain.registerHandler(handler2);
        chain.registerHandler(handler3);

        handler3.handleRequest("1231sdhff  %*^3kihk 443wr23$%");
    }

运行结果如下:

1.2.png

上面只是很简单的实现了和Filter一样的作用,但是不像Java Web中的结构那么清晰。

通过上面两个例子能够清楚的了解责任链模式的工作方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值