作为软件工程师,我个人的目标是构建可运行,解决问题并且可维护,可扩展和高性能的软件。为此,以有组织的方式编写代码非常重要。因此很清楚每一段代码在做什么,避免重复并提高可维护性。
几周前,我们有一个需要摄取同一对象的要求,但是根据其中一个字段,对其进行完全不同的处理。最简单,最快的方法可能是使用不同的逻辑创建不同的类,并简单地使用多个“ if / else”语句来执行所需的过程。但是,如果我们没有两个流程,但是将来可能只有五个或十个流程,该怎么办?
在快节奏的行业中,我们往往会忘记许多这些问题已经建立了解决方案。因此,仅通过对Google进行快速研究,我就发现了策略模式。我以前曾经实现过这种模式,但是起初我没有想到它。但是,看到这就像隧道尽头的光芒!
策略模式是使得能够在运行时选择的算法的行为的设计模式。在本教程中,我将解释一种使用spring框架并利用其依赖注入能力实现它的方法。
在本教程中,我创建了一个Spring Webflux项目,并为您提供了一些背景信息,该服务通过REST API从电子商务站点获取订单。这些订单可以用于个人或公司客户。
逻辑很简单,如果是来自单个客户的订单,我们希望使用有效的付款方式。我们将动态决定要处理传入订单的类。在下面的代码中,我省略了一些方法和构造函数,但是,我强烈建议您在此处获取完整的项目并自己进行测试。
步骤1:让我们创建订单模型,该模型将用于向我们的API提交订单。
| public class Order {
 public enum MethodOfPayment {
 
 CREDIT_CARD,
 DEBIT_CARD,
 CORPORATE_ACCOUNT
 
 }
 
 public enum OrderType{
 CORPORATE,
 INDIVIDUAL
 }
 
 private Customer customer;
 private OrderType orderType;
 private String corpCode;
 private MethodOfPayment methodOfPayment;
 private Corporation corporation;
 private List<String> articles;
 
 //methods omitted for this post. Visit the github project for more.
 }
 
 | 
步骤2:为您的处理类创建一个接口:
| public interface OrderProcessingService {//In here we define that all implementations must take an order
 // and return an OrderApiResponse.
 Mono<OrderApiResponse> processOrder(Order order);
 
 }
 
 | 
我们已经创建了此接口来定义一种所有处理订单的合同。
步骤3:为每个处理流创建实现,并使用@Component Annotation对其进行注释。
| @Component("CORPORATE")public class CorporateOrderProcessingService implements OrderProcessingService {
 
 
 @Override
 public Mono<OrderApiResponse> processOrder(Order order) {
 return Mono.just(order)
 .handle(this.handleOrder());
 }
 
 }
 // Constructor and other methods omitted for this post but available in the full project.
 
 | 
| @Component("INDIVIDUAL")public class IndividualOrderProcessingService implements OrderProcessingService {
 
 @Override
 public Mono<OrderApiResponse> processOrder(Order order){
 return Mono.just(order)
 .handle(this.handleOrder());
 }
 
 }
 // Constructor and other methods omitted for this post but available in the full project.
 
 | 
注意我们如何给每个注释一个特定的名称,该名称与我们的订单模型中定义的OrderType枚举相关。这将帮助我们确定对特定消息使用哪种实现。
第4步:在Controller类中将所有内容粘合在一起:
| @RestControllerpublic class OrderController {
 
 private final Map<String, OrderProcessingService> orderProcessingServices;
 
 //Spring will autowire our map with both immplementations and the Component name as the key
 public OrderController(Map<String, OrderProcessingService> orderProcessingServices) {
 this.orderProcessingServices = orderProcessingServices;
 }
 
 @PostMapping("/order")
 public Mono<OrderApiResponse> onNewOrder(@RequestBody Order receivedOrder) {
 
 return this.orderProcessingServices.get(receivedOrder.getOrderType().name())
 .processOrder(receivedOrder);
 
 }
 
 }
 
 | 
在此控制器类中,我们使用了带字符串键的Map和OrderProcessingService的实例。Spring的魔力将注入该类型的所有可用bean,并通过其构造函数将组件名称用作此映射中的键。端点/order接受到Order对象以后,我们将基于orderType字段动态选择要使用的策略实现。