modelo de cadeia de responsabilidade
O padrão Chain of Responsibility é um padrão de design comportamental que separa o remetente e o destinatário de solicitações para que as solicitações possam ser organizadas e processadas de forma flexível. Ele funciona passando e processando solicitações ao longo de uma cadeia de processadores até que um processador seja capaz de lidar com a solicitação ou o fim da cadeia.
As principais funções deste modo são:
-
Desacoplamento do remetente e do destinatário da solicitação: o modo de cadeia de responsabilidade dissocia o remetente e o destinatário. O remetente não precisa saber qual destinatário está lidando com a solicitação e o destinatário não precisa saber quem é o remetente da solicitação, melhorando assim o sistema eficiência Flexibilidade e facilidade de manutenção.
-
Organizar e processar solicitações dinamicamente: o modelo Chain of Responsibility pode organizar e processar solicitações dinamicamente, ajustar de forma flexível a ordem e o número de processadores no link de acordo com as condições reais e implementar diferentes lógicas de negócios e estratégias de processamento.
-
Evite a codificação permanente de solicitações: o padrão Chain of Responsibility lida com solicitações por meio de configuração e links, evitando a codificação permanente de solicitações e tornando o sistema mais fácil de expandir e manter.
Cenário de aplicação:
-
O processamento da solicitação envolve vários links ou vários objetos: Quando uma solicitação precisa ser processada por vários links de processamento ou vários objetos, o padrão de cadeia de responsabilidade pode ser usado. Por exemplo, o processamento de solicitações precisa ser processado por vários processadores, como autenticação, log e cache.
-
Seleção dinâmica de processadores: Quando a seleção e a ordem dos processadores precisam ser ajustadas dinamicamente de acordo com a situação real, o padrão Chain of Responsibility pode ser usado. Por exemplo, selecione dinamicamente um processador com base no tipo ou prioridade da solicitação.
-
Cenários em que as solicitações precisam ser filtradas ou interceptadas: Quando as solicitações precisam ser filtradas, interceptadas ou processadas de acordo com as condições, o padrão Cadeia de Responsabilidade pode ser usado. Por exemplo, operações como verificação de permissão, verificação de segurança e verificação de dados são executadas na solicitação.
-
Reduza o acoplamento e melhore a flexibilidade e a manutenibilidade do sistema: quando for necessário reduzir o acoplamento entre o emissor e o receptor e melhorar a flexibilidade e a manutenibilidade do sistema, o padrão da cadeia de responsabilidade pode ser considerado.
Resumindo, o padrão Chain of Responsibility é adequado para cenários em que a cadeia de solicitação de processamento é longa, os processadores são fracamente acoplados e as solicitações precisam ser organizadas e processadas dinamicamente. Ele pode nos ajudar a obter um design de sistema mais flexível, escalável e sustentável.
caso prático
Combinado com anotações personalizadas e @Aspect, podemos aprimorar o componente para ter a função do modo de cadeia de responsabilidade.
Primeiro, precisamos definir uma anotação personalizada para identificar o método ou classe que precisa aplicar o padrão Chain of Responsibility. As seguintes anotações podem ser definidas:
package com.example.demo.design.chain;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyChain {}
接下来,我们使用@Aspect注解创建一个切面类,在切面类中实现责任链模式的逻辑。可以定义如下切面类
package com.example.demo.design.chain;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
@Aspect
@Component
public class ChainHandlerAspect implements InitializingBean {
@Autowired
// 注入所有实现ChainHandler接口的责任链处理器
private List<ChainHandler> chainHandlers;
// 责任链的头节点
private ChainHandler chainHandler;
@Around("@annotation(com.example.demo.design.chain.MyChain)")
public Object checkParam(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs(); // 获取方法的所有参数
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes(); // 获取方法的参数类型列表
for (int i = 0; i < parameterTypes.length; i++) {
if (parameterTypes[i].getName().equals("java.lang.String")) {
chainHandler.handle(new Request((String) args[0]));
}
}
return pjp.proceed();
}
/**
* 构建处理器链
*/
private ChainHandler buildHandlerChain() {
ChainHandler headChainHandler = null;
ChainHandler currentChainHandler = null;
for (ChainHandler chainHandler : chainHandlers) {
if (headChainHandler == null) {
headChainHandler = chainHandler;
currentChainHandler = headChainHandler;
} else {
currentChainHandler.setNextHandler(chainHandler);
currentChainHandler = chainHandler;
}
}
return headChainHandler;
}
@Override
public void afterPropertiesSet() throws Exception {
// 构建责任链
chainHandler = this.buildHandlerChain();
}
}
责任链相关组件
处理器接口
package com.example.demo.design.chain;
public interface ChainHandler {
void handle(Request request);
void setNextHandler(ChainHandler handler);
}
处理器实现类
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1)
public class FirstHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 处理请求
System.out.println("FirstHandler handling request " + request);
// 将请求传递给下一个处理器
if (nextHandler != null) {
nextHandler.handle(request);
}
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(2)
public class SecondHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 处理请求
System.out.println("SecondHandler handling request " + request);
// 将请求传递给下一个处理器
if (nextHandler != null) {
nextHandler.handle(request);
}
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(3)
public class ThirdHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 处理请求
System.out.println("ThirdHandler handling request " + request);
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
以上代码是类同的,通过@Order注解指定了处理器的执行顺序,数字越小,优先级越高。
setNextHandler方法用于设置下一个处理器,接收一个ChainHandler对象作为参数,并将其保存在nextHandler字段中。
Request类
package com.example.demo.design.chain;
public class Request {
private String data;
public Request(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return "Request{" +
"data='" + data + ''' +
'}';
}
}
业务代码组件
package com.example.demo.design.chain;
import org.springframework.stereotype.Component;
@Component
public class BizComponent {
@MyChain
public void process(String data) {
System.out.println(data);
}
}
@MyChain注解用于标记需要应用责任链模式的方法或类。
启动类
package com.example.demo.design.chain;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {
public static void main(String[] args) {
SpringApplication.run(com.example.demo.design.chain.Application.class, args);
}
}
@EnableAspectJAutoProxy注解用于启用AspectJ自动代理功能,使得Spring能够识别和应用切面。
package com.example.demo.design.chain;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
@Data
public class ComponentRunner implements CommandLineRunner {
@Autowired
private BizComponent bizComponent;
@Override
public void run(String... args) throws Exception {
// 执行某个方法(带Chain注解)
bizComponent.process("Hello world!");
}
}
该组件类的执行逻辑是在应用程序启动后自动执行的,可以根据实际需求,在run方法中编写适当的业务逻辑和处理流程。
主要是为了模拟发起请求,可以使用Controller访问的方式。
**执行效果 **
我们可以看到,在执行bizComponent.process("Hello world!")之前,我们已经被注解@MyChain进行增强处理了,所以会经过责任链进行前置处理。
总结
通过这种方式,我们可以灵活地扩展和定制责任链的处理逻辑,通过注解和AOP的方式将责任链与业务组件进行解耦,实现组件的增强和复用。
责任链模式的应用场景很广泛,例如在Web开发中,可以使用责任链模式来处理请求的拦截、验证、日志记录等操作;在工作流引擎中,可以使用责任链模式来实现任务的处理和流转;在事件驱动系统中,可以使用责任链模式来处理事件的触发和传递等等。
通过结合自定义注解和Spring的AOP功能,我们可以更加方便地应用责任链模式,并在开发过程中获得更高的可扩展性和灵活性。这种组件增强的方式使得责任链模式的实现更加简洁、可读性更高,同时也提升了代码的可维护性和可测试性。
总而言之,使用自定义注解和@Aspect实现责任链模式的组件增强,是一种强大的编程技巧,能够有效地将责任链的逻辑与业务组件解耦,提供了一种灵活且可扩展的方式来处理请求和逻辑链的处理。这种结合注解和AOP的方式,使得责任链模式的应用更加简单、优雅,为我们的开发工作带来了便利和效益。
欢迎关注公众号:程序员的思考与落地
公众号提供大量实践案例,Java入门者不容错过哦,可以交流!!