目录
目标
概述
实现
单向设计模式
双向设计模式
目标
熟悉责任链设计模式,了解责任链设计模式的使用场景、具体实现,单链责任链设计模式和双链责任链设计模式的区别。
概述
一、行为设计模式
行为设计模式是设计模式的一种类型。该类型的设计模式关注的重点在于对象的行为(通信和交互),而非对象的创建方式。较为常见的行为设计模式有:观察者模式、策略模式、命令模式、责任链模式等。优点是减少了对象之间的耦合度。
二、责任链模式
请求可能被一个对象(或处理器)或者多个相似的对象(或处理器)处理。责任链模式将多个对象串成一条链,使得请求沿着一条链传递,直到有一个对象能够处理该请求。由此看来,每个对象都有机会处理请求,所以这种模式使得请求的发送者和对象之间的耦合度降低,从而提高了代码的扩展性和可维护性。
优点:
- 使请求的发送者和请求的处理对象(处理器)耦合度降低。
- 动态调整处理对象,可以根据需求新增,删除责任链上的对象,也可以灵活定义对象在链上的排列顺序。
缺点:
- 责任链过长可能会使得处理请求的速度变慢,影响性能。
- 可能存在无法处理请求的情况。
三、单向责任链模式和双向责任链模式的区别
责任链模式将多个对象串成一条链,因此有了前驱对象和后继对象。其中:
单向责任链模式 | 双向责任链模式 | |
责任范围 | 只能将请求传递给链上的下一个对象。 | 能将请求传递给链上的任意对象。 |
优点 | 实现简单,容易维护。 | 支持请求的回溯和撤销,处理请求更灵活。 |
缺点 | 只适用于简单的顺序传递请求。 | 实现复杂,不易维护。需要更多的内存空间。 |
四、使用场景
- 多个对象处理同一个请求时存在优先级关系。
- 在不同的时间处理不同的部分。
- 处理同一个请求的多个对象可以被动态改变。
五、列举责任链模式在成熟的框架中的应用
- Java Servlet API中的Filter过滤器链。
- Spring Framework中的拦截器链(Interceptor Chain)。
- Netty中的ChannelHandler链。
实现
单向设计模式
需求
员工提交报销单申请报销,其中:
- 1000元(含)以下由直接主管审批。
- 1000元以上5000元(含)以下由部门经理审批。
- 5000元以上由总裁批准。
代码
处理器类
package com.ctx.chain.one;
import java.math.BigDecimal;
// CEO处理器
public class CEOHandler extends ExpenseHandler {
// 5000元以上的报销由CEO处理
private static final BigDecimal MINIMUM_APPROVAL_AMOUNT = new BigDecimal(5000);
@Override
public void handleExpense(BigDecimal amount) {
if (amount.compareTo(MINIMUM_APPROVAL_AMOUNT) > 0) {
System.out.println("CEO审批通过,报销金额为:" + amount);
} else {
System.out.println("报销金额太小,不需要CEO审批,报销金额为:" + amount);
}
}
}
package com.ctx.chain.one;
import java.math.BigDecimal;
// 部门经理处理器
public class DepartmentManagerHandler extends ExpenseHandler {
// 1000元以上5000元(含)以下的报销由部门经理处理
private static final BigDecimal MAXIMUM_APPROVAL_AMOUNT = new BigDecimal(5000);
private static final BigDecimal MINIMUM_APPROVAL_AMOUNT = new BigDecimal(1000);
@Override
public void handleExpense(BigDecimal amount) {
if (amount.compareTo(MINIMUM_APPROVAL_AMOUNT) > 0 && amount.compareTo(MAXIMUM_APPROVAL_AMOUNT) <= 0) {
System.out.println("部门经理审批通过,报销金额为:" + amount);
} else {
successor.handleExpense(amount);
}
}
}
package com.ctx.chain.one;
import java.math.BigDecimal;
// 直接主管处理器
public class DirectSupervisorHandler extends ExpenseHandler {
// 1000元(含)以下的报销由直接主管处理
private static final BigDecimal MAXIMUM_APPROVAL_AMOUNT = new BigDecimal(1000);
@Override
public void handleExpense(BigDecimal amount) {
if (amount.compareTo(MAXIMUM_APPROVAL_AMOUNT) <= 0) {
System.out.println("直接主管审批通过,报销金额为:" + amount);
} else {
successor.handleExpense(amount);
}
}
}
处理器抽象类
package com.ctx.chain.one;
import java.math.BigDecimal;
// 责任链模式中的抽象处理器
public abstract class ExpenseHandler {
protected ExpenseHandler successor;
// 设置下一个处理器
public void setSuccessor(ExpenseHandler successor) {
this.successor = successor;
}
// 处理报销请求的方法
public abstract void handleExpense(BigDecimal amount);
}
调用类
package com.ctx.chain.one;
import java.math.BigDecimal;
//调用类
public class Test {
public static void main(String[] args) {
ExpenseHandler directSupervisorHandler = new DirectSupervisorHandler();
ExpenseHandler departmentManagerHandler = new DepartmentManagerHandler();
ExpenseHandler ceoHandler = new CEOHandler();
directSupervisorHandler.setSuccessor(departmentManagerHandler);
departmentManagerHandler.setSuccessor(ceoHandler);
BigDecimal expenseAmount1 = new BigDecimal(500);
BigDecimal expenseAmount2 = new BigDecimal(1500);
BigDecimal expenseAmount3 = new BigDecimal(6000);
directSupervisorHandler.handleExpense(expenseAmount1);
directSupervisorHandler.handleExpense(expenseAmount2);
directSupervisorHandler.handleExpense(expenseAmount3);
}
}
双向设计模式
需求
以受理用户投诉为案例,其中:
- 用户发起投诉,客服受理,客服可以选择:驳回、指派给运维人员,已解决。
- 运维人员处理投诉,可以选择:已解决,指派给运维主管。
- 运维主管处理投诉,可以选择:已解决,未解决。且不管是否解决,该投诉会下发至部门经理。
- 部门经理处理投诉,可以选择:满意,不满意。不满意则驳回至运维主管,满意则下发至客服。
需求流程图
代码
投诉实体类
package com.ctx.chain.two;
public class Complaint {
private String id;
private String content;
private String status;
public Complaint(String id ,String content,String status) {
setId(id);
setContent(content);
setStatus(status);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
处理器抽象类
package com.ctx.chain.two;
public abstract class ComplaintHandler {
protected String name; //处理器名称
protected ComplaintHandler prevHandler; //前一个处理器
protected ComplaintHandler nextHandler; //后一个处理器
public ComplaintHandler(String name) {
this.name = name;
}
public ComplaintHandler() {
}
public void setPrevHandler(ComplaintHandler prevHandler) {
this.prevHandler = prevHandler;
}
public void setNextHandler(ComplaintHandler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleComplaint(Complaint complaint); //处理投诉的抽象方法
}
处理器类
package com.ctx.chain.two.handler;
import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;
import java.util.Scanner;
/**
* 客服
*/
public class CustomerServiceHandler extends ComplaintHandler {
public CustomerServiceHandler(String name) {
super(name);
}
public CustomerServiceHandler() {
super();
}
@Override
public void handleComplaint(Complaint complaint) {
System.out.println("客服接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
Scanner scanner = new Scanner(System.in);
System.out.println("请选择操作:1.驳回,2.指派运维人员,3.已解决。");
int choice = scanner.nextInt();
switch (choice) {
case 1:
complaint.setStatus("已驳回");
System.out.println("投诉已驳回");
break;
case 2:
System.out.println("请选择运维人员:1.张三,2.李四");
int handlerChoice = scanner.nextInt();
if (handlerChoice == 1) {
this.nextHandler = new OperatorHandler("张三");
this.nextHandler.setPrevHandler(this);
} else if (handlerChoice == 2) {
this.nextHandler = new OperatorHandler("李四");
this.nextHandler.setPrevHandler(this);
}
this.nextHandler.handleComplaint(complaint);
break;
case 3:
complaint.setStatus("已解决");
System.out.println("投诉已解决");
break;
default:
System.out.println("无效操作");
break;
}
}
}
package com.ctx.chain.two.handler;
import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;
import java.util.Scanner;
/**
* 部门经理
*/
public class DepartmentManagerHandler extends ComplaintHandler {
public DepartmentManagerHandler(String name) {
super(name);
}
public DepartmentManagerHandler() {
super();
}
@Override
public void handleComplaint(Complaint complaint) {
System.out.println("部门经理" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent()+"问题:"+complaint.getStatus());
Scanner scanner = new Scanner(System.in);
System.out.println("请选择处理意见:1.满意,2.不满意");
int choice = scanner.nextInt();
switch (choice) {
case 1:
complaint.setStatus("已处理");
System.out.println("处理意见已派发给客服");
this.nextHandler = new CustomerServiceHandler();
this.nextHandler.handleComplaint(complaint);
break;
case 2:
complaint.setStatus("驳回");
System.out.println("处理意见已驳回给运维主管");
this.prevHandler.handleComplaint(complaint);
break;
default:
System.out.println("无效操作");
break;
}
}
}
package com.ctx.chain.two.handler;
import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;
import java.util.Scanner;
/**
* 运维人员
*/
public class OperatorHandler extends ComplaintHandler {
public OperatorHandler(String name) {
super(name);
}
public OperatorHandler() {
super();
}
@Override
public void handleComplaint(Complaint complaint) {
System.out.println("运维人员" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
Scanner scanner = new Scanner(System.in);
System.out.println("请选择操作:1.解决,2.转交给主管");
int choice = scanner.nextInt();
switch (choice) {
case 1:
complaint.setStatus("已解决");
System.out.println("投诉已解决");
this.prevHandler.handleComplaint(complaint);
break;
case 2:
this.nextHandler = new SupervisorHandler("主管");
//设置:运维主管的前驱处理器是运维人员
this.nextHandler.setPrevHandler(this);
this.nextHandler.handleComplaint(complaint);
break;
default:
System.out.println("无效操作");
break;
}
}
}
package com.ctx.chain.two.handler;
import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;
import java.util.Scanner;
/**
* 运维主管
*/
public class SupervisorHandler extends ComplaintHandler {
public SupervisorHandler(String name) {
super(name);
}
public SupervisorHandler() {
super();
}
@Override
public void handleComplaint(Complaint complaint) {
System.out.println("运维主管" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
//this.nextHandler = new DepartmentManagerHandler();
//this.nextHandler.setPrevHandler(this);
//this.nextHandler.handleComplaint(complaint);
Scanner scanner = new Scanner(System.in);
System.out.println("请选择操作:1.解决,2.转交给部门经理。");
int choice = scanner.nextInt();
switch (choice) {
case 1:
complaint.setStatus("已解决");
System.out.println("投诉已解决");
this.nextHandler = new DepartmentManagerHandler("陈天相");
//设置:部门经理的前驱处理器是运维主管
this.nextHandler.setPrevHandler(this);
nextHandler.handleComplaint(complaint);
break;
case 2:
complaint.setStatus("未解决");
System.out.println("投诉未解决");
this.nextHandler = new DepartmentManagerHandler("陈天相");
//设置:部门经理的前驱处理器是运维主管
this.nextHandler.setPrevHandler(this);
nextHandler.handleComplaint(complaint);
break;
default:
System.out.println("无效操作");
break;
}
}
}
调用类
package com.ctx.chain.two;
import com.ctx.chain.two.handler.CustomerServiceHandler;
import com.ctx.chain.two.handler.DepartmentManagerHandler;
import com.ctx.chain.two.handler.OperatorHandler;
import com.ctx.chain.two.handler.SupervisorHandler;
public class Test {
public static void main(String[] args) {
Complaint complaint = new Complaint("1","网络不稳定","待处理");
ComplaintHandler customerServiceHandler = new CustomerServiceHandler();
ComplaintHandler operatorHandler = new OperatorHandler();
ComplaintHandler supervisorHandler = new SupervisorHandler();
ComplaintHandler departmentManagerHandler = new DepartmentManagerHandler();
customerServiceHandler.setNextHandler(operatorHandler);
operatorHandler.setNextHandler(supervisorHandler);
supervisorHandler.setNextHandler(supervisorHandler);
departmentManagerHandler.setNextHandler(customerServiceHandler);
customerServiceHandler.handleComplaint(complaint);
}
}