Java - GoF设计模式详解15(责任链模式)
十五、责任链模式
1,基本介绍
(1)责任链模式(Chain of Responsibility):把可以响应请求的对象链接起来,并在链中传递请求,直到有一个对象处理这个请求。从而保证多个对象都有机会处理请求,减少请求的发送者与接收者之间的耦合。
(2)该模式中包含的角色及其职责如下:
- 抽象处理者(Handler)角色:定义了处理请求的接口,并且可以设置后继处理者。
- 具体处理者(Concrete Handler)角色:实现了处理请求的方法,并且可以设置后继处理者。如果无法处理请求,则将请求转发给后继处理者。
2,使用样例
(1)下面我通过用户订单请求的处理(订货量小于 1000 的由经理处理,小于 10000 的由主任处理,大于等于 10000 的由董事长处理)来演示责任链模式的使用。首先我们定义一个订单请求类 OrderRequest:
// 订单请求类 public class OrderRequest { private String customer; //客户姓名 private int amount; //订货量 public OrderRequest(String customer, int amount) { this.customer = customer; this.amount = amount; } public String getCustomer() { return customer; } public int getAmount() { return amount; } }
(2)接着定义一个抽象的处理者类 OrderHandler:
// 抽象处理者类 public abstract class OrderHandler { // 下一个处理者 protected OrderHandler successor; // 设置下一个处理者 public void setSuccessor(OrderHandler successor) { this.successor = successor; } // 处理订单请求的方法 public abstract void handleOrder(OrderRequest request); }
(3)然后就是定义3个具体的处理者类,分别是 ManagerOrderHandler、DirectorOrderHandler 和 CEOOrderHandler:
// 经理级别订单处理 public class ManagerOrderHandler extends OrderHandler { @Override public void handleOrder(OrderRequest request) { if (request.getAmount() < 1000) { System.out.println("经理处理来自" + request.getCustomer() + "的订单,订货量为" + request.getAmount()); } else { successor.handleOrder(request); } } } // 主任级别订单处理 public class DirectorOrderHandler extends OrderHandler { @Override public void handleOrder(OrderRequest request) { if (request.getAmount() < 10000) { System.out.println("主任处理来自" + request.getCustomer() + "的订单,订货量为" + request.getAmount()); } else { successor.handleOrder(request); } } } // 董事长级别订单处理 public class CEOOrderHandler extends OrderHandler { @Override public void handleOrder(OrderRequest request) { System.out.println("董事长处理来自" + request.getCustomer() + "的订单,订货量为" + request.getAmount()); } }
(4)最后我们使用责任链模式来处理用户的订单请求,我们先设置了三个处理者对象 manager、director 和 ceo,并且设置了它们的后继处理者。然后,我们发送了 4 个订单请求,每个请求都会在责任链上流动,直到有一个处理者能够处理该请求为止。
public class Test { public static void main(String[] args) { // 创建处理者对象 OrderHandler manager = new ManagerOrderHandler(); OrderHandler director = new DirectorOrderHandler(); OrderHandler ceo = new CEOOrderHandler(); // 设置后继处理者 manager.setSuccessor(director); director.setSuccessor(ceo); // 发送请求 manager.handleOrder(new OrderRequest("乔布斯", 12000)); manager.handleOrder(new OrderRequest("李老板", 500)); manager.handleOrder(new OrderRequest("hangge", 1500)); manager.handleOrder(new OrderRequest("刘总", 50000)); } }
附一:JDK 中的责任链模式
(1)java.util.logging 包中的日志系统使用了责任链模式。当 Logger 对象收到一条日志消息时,它会将消息发送到它的后继节点。Logger 对象的后继节点可以是其他 Logger 对象,也可以是控制台、文件或其他输出目的地。这样,Logger 对象就可以将日志消息发送到多个输出目的地,从而实现了责任链模式的效果。
public class Test { private static final Logger logger = Logger.getLogger(Test.class.getName()); public static void main(String[] args) { logger.info("This is an info message."); logger.warning("This is a warning message."); logger.severe("This is a severe message."); } }
(2)在上面的示例代码中,我们并没有显式地创建 Logger 对象的后继节点。这是因为,在默认情况下,Logger 对象的后继节点是由 Java 虚拟机的日志记录配置文件决定的。如果要修改 Logger 对象的后继节点,可以使用 Logger 对象的 addHandler() 方法来添加新的后继节点。例如,可以使用以下代码来将一个文件输出流添加为 Logger 对象的后继节点:
- 下面的代码中,我们使用了 FileHandler 类来创建一个文件输出流,然后使用 Logger 对象的 addHandler() 方法将该输出流添加为 Logger 对象的后继节点。这样,Logger 对象就可以将日志消息发送到两个输出目的地:控制台和文件。
public class Test { private static final Logger logger = Logger.getLogger(Test.class.getName()); public static void main(String[] args) throws Exception { FileHandler fileHandler = new FileHandler("example.log"); logger.addHandler(fileHandler); logger.info("This is an info message."); logger.warning("This is a warning message."); logger.severe("This is a severe message."); } }
附二:Spring 中的责任链模式
1,Spring MVC 中的拦截器(Interceptor)
拦截器是 Spring MVC 的一种常用机制,用于拦截请求并执行特定的操作。拦截器通常是按照定义的顺序依次执行,形成一个责任链。
2,Spring AOP 中的切面(Aspect)
Spring AOP 支持在特定方法调用前或之后执行某些操作,这些操作被称为切面。多个切面可以通过配置的优先级或执行顺序来构建责任链。
3,Spring 的事件传递机制(ApplicationEvent)
Spring 支持在应用中传递事件,这些事件可以被多个监听器(Listener)接收并处理。这些监听器可以按照定义的优先级或执行顺序依次执行,形成一个责任链。
附三:JavaScript 中的责任链模式
在 JavaScript 中,可以使用事件冒泡(event bubbling)机制来实现事件的传递。在事件冒泡中,事件从目标元素开始向上传递,每经过一个父元素就被触发一次。这种机制可以让多个元素对同一个事件进行响应,形成一个责任链。