设计模式笔记_行为型_责任链模式

1. 责任链模式介绍

责任链模式(Chain of Responsibility)是一种行为设计模式,它允许将多个处理器(处理对象)连接成一条链,并沿着这条链传递请求,直到有一个处理器处理它为止。职责链模式的主要目的是避免请求的发送者与多个请求处理者之间的耦合。

**类比场景:**想象一下,客户服务中心有多个层级的客服人员:初级客服、高级客服和经理。客户的问题会从初级客服开始,逐级向上转发,直到有一个客服能够解决问题。

**组成结构:**职责链模式主要包含以下几个部分:

  1. 抽象处理者(Handler):定义一个处理请求的接口,并包含一个指向下一个处理者的引用。
  2. 具体处理者(ConcreteHandler):实现处理请求的具体逻辑,并决定是否将请求传递给下一个处理者。
  3. 处理器链(HandlerChain): 在职责链模式的实现中,使用HandlerChain不是必须的,但是一种常见的做法。HandlerChain 的使用主要是为了简化链的管理,使得链的创建和维护更加便捷和集中。
  4. 客户端(Client):负责创建处理链,并向链中的第一个处理者发送请求。

优缺点分析:

  • 优点
    • 降低耦合:请求发送者和接收者之间的耦合度降低,灵活地新增和修改处理者。
    • 动态组合:可以方便地改变链内的成员或调动它们的次序。
  • 缺点
    • 不保证请求被处理:如果链的末端没有处理请求,可能会导致请求不被处理。这个场景可以通过责任链的变体实现,让请求被所有处理器都处理。
    • 性能问题:链过长可能导致性能问题,因为请求需要经过多个处理者。

适用场景:

  • 需要动态地指定请求的处理者。
  • 有多个对象可以处理某个请求,但具体处理者不确定。
  • 希望请求的发送者和接收者解耦。

2. 代码演示

责任链有链表和列表两种实现方式,这里分别演示。演示场景围绕"初级客服、高级客服和经理处理客诉"展开。

2.1 链表实现

**抽象处理者(Handler):**链式实现方式中,抽象处理类是一个抽象类,里面定义了处理请求的接口(这里是doHandle接口),并包含指向下一个处理者的引用(这里对应nextHandler属性)。通常还会将调用下个处理器的通用逻辑提取出来(对应handleRequest方法),这样具体处理器类只需要实现自己的业务逻辑就可以了。

java 复制代码
// 抽象处理者
public abstract class CustomerServiceHandler {
    //下一个处理器的对象
    protected CustomerServiceHandler nextHandler;

    public void setNextHandler(CustomerServiceHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

   //调用下个处理器的逻辑,原本放在具体处理器中;属于通用逻辑,这里利用模版模式提取到父类
    public void handleRequest(String request) {
        boolean handled = doHandle(request);
        //gof定义:若当前处理器不能处理,则需要向下个处理器传递; 否则结束
        if (!handled && nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }

    //抽象处理逻辑:具体实现放在各handler自己实现的  doHandle() 函数里
    public abstract boolean doHandle(String request);

}

具体处理者(ConcreteHandler):

java 复制代码
//具体处理者 - 初级客服
public class JuniorCustomerService extends CustomerServiceHandler {
    @Override
    public boolean doHandle(String request) {
        if (request.equals("basic")) {
            System.out.println("junior customer service handle");
            return true;
        }
        return false;
    }
}

// 具体处理者 - 高级客服
public class SeniorCustomerService extends CustomerServiceHandler {
    @Override
    public boolean doHandle(String request) {
        if (request.equals("advanced")) {
            System.out.println("senior customer service handle");
            return true;
        }
        return false;
    }
}

// 具体处理者 - 经理
public class Manager extends CustomerServiceHandler {
    @Override
    public boolean doHandle(String request) {
        if (request.equals("complex")) {
            System.out.println("manager customer service handle");
            return true;
        }
        return false;
    }
}

处理器链(HandlerChain): HandlerChain不是必须的,在某些情况下,直接在客户端代码中构建职责链是足够的,尤其是链简单且变化不频繁的时候。然而,在处理复杂链或需要动态调整链的场景下,引入 HandlerChain 可以提高代码的清晰度和灵活性。通过HandlerChain集中管理handlers,负责链中处理者的添加、移除和遍历,简化链的管理。

java 复制代码
public class CustomerServiceHandlerChain {
    private CustomerServiceHandler firstHandler;
    private CustomerServiceHandler lastHandler;

    //给链表中添加处理器
    public void addHandler(CustomerServiceHandler handler) {
        if (firstHandler == null) {
            //链表头为null,放在链表头
            firstHandler = handler;
            lastHandler = handler;
        } else {
            //否则放在链表尾
            lastHandler.setNextHandler(handler);
            lastHandler = handler;
        }
    }

    //执行链表中的处理器:从第一个处理器开始执行
    public void handleRequest(String request) {
        if (null != firstHandler) {
            firstHandler.handleRequest(request);
        }
    }
}

客户端代码:

java 复制代码
public class CustomerServiceChainDemo {
    public static void main(String[] args) {
        CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();
        handlerChain.addHandler(new JuniorCustomerService());
        handlerChain.addHandler(new SeniorCustomerService());
        handlerChain.addHandler(new Manager());

        // 测试不同请求
        //handlerChain.handleRequest("basic");
        handlerChain.handleRequest("advanced");
    }
}

对应的类图:

2.2 列表实现

列表实现方式更加简单,与链表实现的差异点:

  • 抽象处理者(handler)改用interface (无需存储对下一个处理者的引用)
  • HandlerChain类中用列表而非链表来保存所有的处理器
  • 在HandlerChain中,依次调用每个handler(链表对nextHandler的调用放在抽象处理者类中)

**抽象处理者(Handler):**列表实现方式中,抽象处理者是一个接口,定义处理请求的方法。

java 复制代码
//抽象处理者
public interface CustomerServiceHandler {
    boolean handlerRequest(String request);
}

具体处理者(ConcreteHandler):

java 复制代码
//具体处理者 - 初级客服
public class JuniorCustomerService implements CustomerServiceHandler {
    @Override
    public boolean handlerRequest(String request) {
        if (request.equals("basic")) {
            System.out.println("junior customer service handle");
            return true;
        }
        return false;
    }
}

//具体处理者 - 高级客服
public class SeniorCustomerService implements CustomerServiceHandler {
    @Override
    public boolean handlerRequest(String request) {
        if (request.equals("advanced")) {
            System.out.println("senior customer service handle");
            return true;
        }
        return false;
    }
}

//具体处理者 - 经理
public class Manager implements CustomerServiceHandler {
    @Override
    public boolean handlerRequest(String request) {
        if (request.equals("complex")) {
            System.out.println("manager customer service handle");
            return true;
        }
        return false;
    }
}

**处理器链(HandlerChain):**HandlerChain类中用列表而非链表来保存所有的处理器,并在HandlerChain的handle()函数中,依次调用每个处理器的handle()函数。

java 复制代码
public class CustomerServiceHandlerChain {
    private List<CustomerServiceHandler> handlerList = new ArrayList<>();

    public void addHandler(CustomerServiceHandler handler) {
        handlerList.add(handler);
    }

    public void handleRequest(String request) {
        for (CustomerServiceHandler handler : handlerList) {
            //gof定义: 若当前处理器不能处理,则向下一个处理器传递; 否则结束
            Boolean handledResult = handler.handlerRequest(request);
            if (handledResult) {
                break;
            }
        }
    }
}

客户端代码:

java 复制代码
public class CustomerServiceChainDemo {
    public static void main(String[] args) {
        CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();
        handlerChain.addHandler(new JuniorCustomerService());
        handlerChain.addHandler(new SeniorCustomerService());
        handlerChain.addHandler(new Manager());
        // 测试不同请求
        handlerChain.handleRequest("basic");
    }
}

对应的类图:

2.3 变体:所有handler都处理一遍

上述实现是按照gof定义:如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求,整个流程就会结束。

职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。还是使用上述客服场景,假设用户需要退款,需要 初级/高级/经理 三级客服签字确认。

列表实现的代码如下:

java 复制代码
//抽象处理者
public interface CustomerServiceHandler {
    void handlerRequest(String request);
}
java 复制代码
//具体处理者 - 初级客服
public class JuniorCustomerService implements CustomerServiceHandler {
    @Override
    public void handlerRequest(String request) {
        //doSomething ...
        System.out.println("junior customer service handle");
    }
}

//具体处理者 - 高级客服
public class SeniorCustomerService implements CustomerServiceHandler {
    @Override
    public void handlerRequest(String request) {
        //doSomething ...
        System.out.println("senior customer service handle");
    }
}

//具体处理者 - 经理
public class Manager implements CustomerServiceHandler {
    @Override
    public void handlerRequest(String request) {
        //doSomething ...
        System.out.println("manager customer service handle");
    }
}
java 复制代码
//处理器链
public class CustomerServiceHandlerChain {
    private List<CustomerServiceHandler> handlerList = new ArrayList<>();

    public void addHandler(CustomerServiceHandler handler) {
        handlerList.add(handler);
    }

    public void handleRequest(String request) {
        for (CustomerServiceHandler handler : handlerList) {
            //变体类型: 不关注 handled值,请求会被所有的处理器都处理一遍,不存在中途终止的情况
            handler.handlerRequest(request);
        }
    }
}
java 复制代码
//客户端代码
public class CustomerServiceChainDemo {
    public static void main(String[] args) {
        CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();
        handlerChain.addHandler(new JuniorCustomerService());
        handlerChain.addHandler(new SeniorCustomerService());
        handlerChain.addHandler(new Manager());
        //发起退款
        handlerChain.handleRequest("退款100元");
    }
}