前言
面试,对于每一个求职者来说,都是一段难忘的经历。而面试的流程,就像是一种深藏不露的设计模式,每一轮的面试官都肩负着特定的职责。一个求职者的面试历程,恰如一次客户端的请求过程。
在之前的设计模式系列文章中,我们已经探讨了创建型设计模式的奥秘,感兴趣的小伙伴们不妨再去探寻那些知识的宝藏。接下来,我要为大家揭开行为型设计模式的神秘面纱,特别是其中的责任链模式。
大纲
定义
何为责任链?它的原理又是什么?简而言之,责任链是将请求的发送和接收进行解耦,让多个接收对象都有机会处理这个请求。这些接收对象被串联成一条链,沿着这条链,请求会被逐一传递,直到链上的某个接收对象能够妥善处理它。这一美妙的定义,源自《设计模式之美》。
让我们再来看一张官方图解,更直观地理解责任链的构成。在图解中,我们看到了Client(客户端)实例化一个处理器的链,并在第一个链对象中调用handleRequest方法。Handle(处理器)是一个抽象类,为实际处理器提供继承并实现handleRequst方法的机会,以处理请求。而ConcreteHandler(具体处理器)则是继承了handler的类,实现handleRequst方法,负责处理业务逻辑。不同业务模块拥有不同的ConcreteHandler。
如果我们用面试的流程来模拟责任链,会是什么样子的呢?
代码实现
假设我们现在去一家公司面试,第一次是一面,第二次是二面,第三次直接通过。那么,这个模拟面试的代码是如何编写的呢?
我们定义一个抽象的Handler处理器,并为其添加一个抽象的handleRequest方法。接下来,我将展示FirstInterview类的代码,它继承了Handler类,并实现了handleRequest方法。在这个方法中,我们会判断是否是当前处理器应该处理的业务逻辑,如果不是,则向下传递。
public abstract class Handler {
protected Handler handler;
public void setHandler(Handler handler) {
this.handler = handler;
}
public abstract void handleRequest(Integer times);
}
让我们继续构建FirstInterview的处理器。在这个处理器内部,我们实现了handleRequest方法,它会判断是否是当前处理应该处理的业务逻辑。如果不是,它会将请求传递给链上的下一个处理器。同样地,SecondInterview的代码与FirstInterview基本一致。我们来看ThirdInterview类的实现。
public class ThreeInterview extends Handler {
@Override
public void handleRequest(Integer times) {
if (times == 3) {
System.out.println("这是第三次面试," + times + "。恭喜你通过面试!HR将与你联系!");
}
// 其他的逻辑处理或向下传递请求
}
}
责任链模式:业务处理的优雅流程
在一段精心设计的程序中,不同的业务处理流程往往由不同的处理器负责。这些处理器通过责任链模式协同工作,确保每个处理器都能专注于自己的业务逻辑,而无需关心其他部分。这种设计不仅使代码结构清晰,而且易于维护和扩展。
以面试过程为例,想象一下有三个面试环节:初试、复试和终审。每个环节都由一个处理器负责,这些处理器形成一个责任链。初试处理器接收请求并进行处理,如果进入下一环节,复试处理器会接收并处理请求,最后终审处理器决定是否录用。这个过程非常直观,体现了责任链模式的核心理念。
这种设计模式不仅在面试场景中有所应用,在许多框架源码中也得到了体现。例如,SpringMVC中的ServletFilter和Spring的SpringInterceptor都运用了责任链模式。在RPC框架DUBBO中,也体现了责任链的思想。在实际业务场景中,我们可以利用这种思想来实现更灵活的业务处理流程。
以商品详情展示为例,想象一下我们有一个复杂的商品详情页面,包含了头图、商品信息、SKU信息、配送地址和分期付款等多个模块。为了有效地组装这些内容并展示给用户,我们可以设计一个责任链来处理这些业务逻辑。每个模块都有自己的处理器,这些处理器依次处理请求,最终生成完整的商品详情展示。
在某些特殊业务场景中,我们需要对服务调用进行限制,确保只有特定的场景才能调用某些服务。例如,商品的库存修改服务只允许下单、购物车、添加修改商品等指定场景调用。为了实现这种功能,我们可以实现一个DUBBO,对RPC调用进行选择性过滤。具体的实现方法是修改ConsumerContextFilter消费者,并在其中添加服务名称作为Attachments的一部分。在Provider端,我们可以写一个ProviderFilter来拦截并处理特定的服务调用。
责任链模式是一种优雅的业务处理流程设计方式。通过合理地运用这种模式,我们可以实现代码结构的清晰化、业务处理的灵活化以及系统的可扩展性。无论是在框架源码中还是实际业务场景中,责任链模式都有着广泛的应用。抽象数据处理器类与业务模块处理器实例解析
在一个模块化的系统中,我们往往会通过抽象类来处理具有共性逻辑的数据请求。在这个例子中,我们首先定义了一个抽象类 `AbstractDataHandler`,它提供了一个处理模块化数据的框架,具体的实现细节则通过抽象方法 `doRequest` 来定义。这是一个典型的模板方法设计模式的应用,允许子类在不改变原有方法逻辑的基础上,提供特定的实现细节。
然后,我们有一个 `DataAggregation` 类,它的主要作用是将商品信息和库存信息的处理结果整合到一起,并返回一个Map结构的数据。这个类通过 `@Autowired` 注解注入了 `SkuInfoHandler` 和 `ItemInfoHandler` 实例,然后在 `convertItemDetail` 方法中调用这两个处理器的 `doRequest` 方法来获取数据。这是一种典型的依赖注入的应用,使得类之间的耦合度降低,提高了系统的可维护性和可扩展性。
最后的测试代码展示了如何使用这个系统。它首先通过加载Spring的应用上下文来获取 `DataAggregation` 类的实例,然后调用 `convertItemDetail` 方法来获取商品和库存信息的Map结构数据,并将结果打印出来。这是一个典型的Spring框架下的单元测试流程。
这个例子展示了如何在Spring框架下使用抽象类、依赖注入和面向对象编程的方式来构建一个模块化的数据处理系统。这种设计方式使得系统的结构清晰、易于维护,并且具有良好的可扩展性。另一种编写代码的方式,是将每一个需要处理的Handler加载到一个List容器中。通过这种方式,我们可以逐一调用每个Handler中的doRequest方法,以应对不同的业务场景。这种写法使得代码结构清晰,每个Handler都可以被复用,业务逻辑一目了然。这样的代码不仅易于阅读,也易于维护。
设计模式并非一成不变,选择适合自己当前业务的模式才是最重要的。我们应当深入理解前辈的设计思想,并根据自己的需求进行组合创新。在此,我想分享一种处理Handler的方式,即将它们加载到List容器中并循环调用。这种做法能让代码结构清晰,业务逻辑一目了然,使开发者感到舒适。
在此分享结束,接下来我将继续为大家分享行为型设计模式的相关知识。感谢大家的关注和支持。
作者:敖丙
版权声明:本文链接为
文章来自《钓虾网小编|www.jnqjk.cn》整理于网络,文章内容不代表本站立场,转载请注明出处。