使用Spring實施策略模式 - javarevisited

banq發表於2020-03-31

作為軟體工程師,我個人的目標是構建可執行,解決問題並且可維護,可擴充套件和高效能的軟體。為此,以有組織的方式編寫程式碼非常重要。因此很清楚每一段程式碼在做什麼,避免重複並提高可維護性。
幾周前,我們有一個需要攝取同一物件的要求,但是根據其中一個欄位,對其進行完全不同的處理。最簡單,最快的方法可能是使用不同的邏輯建立不同的類,並簡單地使用多個“ 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類中將所有內容粘合在一起:

@RestController
public 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欄位動態選擇要使用的策略實現。

 

相關文章