有如下业务场景,需要对请求接口做一系列的校验,那么很容易写出以下伪代码,利用抛出异常拦截错误请求参数:
public static void main(String[] args) {
// ...
try{
checkSecurity();
checkParams();
checkRule();
} catch (Exception e){
// ...
}
}
private static void checkSecurity(){
// ...
throw new RuntimeException();
}
private static void checkParams(){
// ...
throw new RuntimeException();
}
private static void checkRule(){
// ...
throw new RuntimeException();
}
使用异常来校验,那么后续逻辑越来复杂的话:
如异常只能返回异常信息,不能返回更多字段,这时候需要自定义异常类。
异常的处理效率比条件判断的方式低很多。异常设计的初衷是解决程序运行中的各种意外情况,不应该用来做流程控制、条件控制。
这时候可以使用责任链模式
责任链模式为请求的接收创建了一个执行链,链上有多个节点,每个节点都有可能满足条件匹配然后处理请求事务。当某个节点处理完了,可以根据业务需求传递给下一个节点继续处理或返回处理完毕。
一,利用模版方法准备一个抽象类,作为所有责任节点的父类,在这个类里:
public abstract class AbstractHandler {
// 指向下一个责任节点属性
private AbstractHandler nextHandler;
// 设置下一个对象的set方法
public void setNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
public AbstractHandler getNextHandler() {
return this.nextHandler;
}
// 留给子类做差异化实现
abstract boolean doFilter();
// 对外提供的入口
public boolean filter(){
// 执行本节点的逻辑。如果校验通过则继续下节点,失败则直接返回
boolean b = doFilter();
if(b) {
// 指向下一节点,如果下节点为空则代表当前就是最后一个节点
if (this.nextHandler != null){
return this.nextHandler.filter();
}else {
return false;
}
} else {
return false;
}
}
}
各实现类:
@Component
@Order(1)
public class CheckSecurityHandler extends AbstractHandler {
@Override
boolean doFilter() {
}
}
@Component
@Order(1)
public class CheckRuleHandler extends AbstractHandler {
@Override
boolean doFilter() {
}
}
一次性初始化所有的责任链对象(不是必须)
@Component
public class ChainOfResponseDemo {
@Autowired
private List<AbstractHandler> abstractHandlerList;
private AbstractHandler abstractHandler;
/* @PostConstruct注解的方法在项目启动的时候执行这个方法,
也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。
* */
@PostConstruct
public void initializeHandlerChain(){
for (int i = 0; i < this.abstractHandlerList.size(); i++) {
if ( i == 0){
abstractHandler = abstractHandlerList.get(0);
} else {
AbstractHandler lastHandler = abstractHandlerList.get(i - 1);
AbstractHandler nextHandler = abstractHandlerList.get(i);
lastHandler.setNextHandler(nextHandler);
}
}
}
// 对外提供的入口
public boolean execute(){
return abstractHandler.filter();
}
public AbstractHandler getAbstractHandler() {
return abstractHandler;
}
public void setAbstractHandler(AbstractHandler abstractHandler) {
this.abstractHandler = abstractHandler;
}
}
方法使用@PostConstruct 执行顺序:
其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象a和对象p,才能执行注入。
所以,如果一个类A中有个成员变量p被@Autowried注解,那么@Autowired注入是发生在A的构造方法执行完之后的。
如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么久无法在构造函数中实现。
为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。
Constructor >> @Autowired >> @PostConstruct
当然也可以不用一次初始化所有责任链对象,而是在使用时,再将需要用到的责任对象创建、灵活组合排序。
参考:https://blog.csdn.net/cui_yonghua/article/details/93462893
当发生一个事件时,根据需求要触发多个不同操作,就可以用观察者模式实现类似 发布-订阅的模式。
用一个Subject类:
所有的观察者,可以统一继承一个抽象类,各自都要自己实现接收通知的方法体。
需要用到的哪些观察者,都可以在客户端自行向Subject中的容器加入(订阅),就可以被Subject通知到
Subject类:
public class Subject {
private List<AbstractObserver> container = new ArrayList<>();
public void notifyAllObserver(String...args) {
for (AbstractObserver observer : container) {
observer.observed(); // 对容器中现存的观察者逐一通知
}
}
public void addObserver(AbstractObserver observer) {
this.container.add(observer);
}
public void removeObserver(AbstractObserver observer) {
this.container.remove(observer);
}
}
观察者
public abstract class AbstractObserver {
public abstract void observed();
}
public class TaskObserver1 extends AbstractObserver {
@Override
public void observed() {
System.out.println("TaskObserver1...被通知到,我要开始睡觉了");
}
}
public class TaskObserver2 extends AbstractObserver {
@Override
public void observed() {
System.out.println("TaskObserver2...被通知到,我要开始学习了");
}
}
客户端。使用演示
public static void main(String[] args) {
Subject subject = new Subject();
TaskObserver1 taskObserver1 = new TaskObserver1();
TaskObserver2 taskObserver2 = new TaskObserver2();
subject.addObserver(taskObserver1);
subject.addObserver(taskObserver2);
subject.notifyAllObserver();
}
扩展功能:
可以灵活的将 taskObserver1 添加或移除,以适应不同的业务场景。这一步还可以根据简单工厂,抽取成不同场景下需要通知不同观察者的固定实现。
notifyAllObserver 方法里也可以根据参数,选择性通知不同的observer。
observed() 方法也可以设置参数,如observed(AbstractObserver observer),可以实现,当一个observer收到消息时,再动态的对一个observe做添加或移除…等操作。