使用Spring实施策略模式 - javarevisited

作为软件工程师,我个人的目标是构建可运行,解决问题并且可维护,可扩展和高性能的软件。为此,以有组织的方式编写代码非常重要。因此很清楚每一段代码在做什么,避免重复并提高可维护性。

几周前,我们有一个需要摄取同一对象的要求,但是根据其中一个字段,对其进行完全不同的处理。最简单,最快的方法可能是使用不同的逻辑创建不同的类,并简单地使用多个“ if / else”语句来执行所需的过程。但是,如果我们没有两个流程,但是将来可能只有五个或十个流程,该怎么办?

在快节奏的行业中,我们往往会忘记许多这些问题已经建立了解决方案。因此,仅通过对Google进行快速研究,我就发现了策略模式。我以前曾经实现过这种模式,但是起初我没有想到它。但是,看到这就像隧道尽头的光芒!

策略模式 是使得能够在运行时选择的算法的行为的设计模式。在本教程中,我将解释一种使用spring框架并利用其依赖注入能力实现它的方法。

在本教程中,我创建了一个Spring Webflux项目,并为您提供了一些背景信息,该服务通过REST API从电子商务站点获取订单。这些订单可以用于个人或公司客户。

逻辑很简单,如果是来自单个客户的订单,我们希望使用有效的付款方式。我们将动态决定要处理传入订单的类。在下面的代码中,我省略了一些方法和构造函数,但是,我强烈建议您在 此处 获取完整的项目并自己进行测试。

步骤1:让我们创建订单模型,该模型将用于向我们的API提交订单。

<b>public</b> <b>class</b> Order {

  <b>public</b> enum MethodOfPayment {

    CREDIT_CARD,
    DEBIT_CARD,
    CORPORATE_ACCOUNT

  }

  <b>public</b> enum OrderType{
    CORPORATE,
    INDIVIDUAL
  }

  <b>private</b> Customer customer;
  <b>private</b> OrderType orderType;
  <b>private</b> String corpCode;
  <b>private</b> MethodOfPayment methodOfPayment;
  <b>private</b> Corporation corporation;
  <b>private</b> List<String> articles;

  <font><i>//methods omitted for this post. Visit the github project for more.</i></font><font>
}
</font>

步骤2:为您的处理类创建一个 接口

<b>public</b> <b>interface</b> OrderProcessingService {
 <font><i>//In here we define that all implementations must take an order</i></font><font>
  </font><font><i>// and return an OrderApiResponse.</i></font><font>
  Mono<OrderApiResponse> processOrder(Order order);

}
</font>

我们已经创建了此接口来定义一种所有处理订单的合同。

步骤3:为每个处理流创建 实现 ,并使用@Component Annotation对其进行注释。

@Component(<font>"CORPORATE"</font><font>)
<b>public</b> <b>class</b> CorporateOrderProcessingService implements OrderProcessingService {


  @Override
  <b>public</b> Mono<OrderApiResponse> processOrder(Order order) {
    <b>return</b> Mono.just(order)
        .handle(<b>this</b>.handleOrder());
  }

}
  </font><font><i>// Constructor and other methods omitted for this post but available in the full project.</i></font><font>
</font>
@Component(<font>"INDIVIDUAL"</font><font>)
<b>public</b> <b>class</b> IndividualOrderProcessingService implements OrderProcessingService {

  @Override
  <b>public</b> Mono<OrderApiResponse> processOrder(Order order){
    <b>return</b> Mono.just(order)
          .handle(<b>this</b>.handleOrder());
  }
  
}
  </font><font><i>// Constructor and other methods omitted for this post but available in the full project.</i></font><font>
</font>

注意我们如何给每个注释一个特定的名称,该名称与我们的订单模型中定义的OrderType枚举相关。这将帮助我们确定对特定消息使用哪种实现。

第4步:在 Controller 类中将所有内容粘合在一起:

@RestController
<b>public</b> <b>class</b> OrderController {

  <b>private</b> <b>final</b> Map<String, OrderProcessingService> orderProcessingServices;
  
  <font><i>//Spring will autowire our map with both immplementations and the Component name as the key</i></font><font>
  <b>public</b> OrderController(Map<String, OrderProcessingService> orderProcessingServices) {
    <b>this</b>.orderProcessingServices = orderProcessingServices;
  }

  @PostMapping(</font><font>"/order"</font><font>)
  <b>public</b> Mono<OrderApiResponse> onNewOrder(@RequestBody Order receivedOrder) {
   
    <b>return</b> <b>this</b>.orderProcessingServices.get(receivedOrder.getOrderType().name())
        .processOrder(receivedOrder);

  }

}
</font>

在此控制器类中,我们使用了带字符串键的Map和OrderProcessingService的实例。Spring的魔力将注入该类型的所有可用bean,并通过其构造函数将组件名称用作此映射中的键。端点/order接受到Order对象以后,我们将基于orderType字段动态选择要使用的策略实现。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章