策略模式与桥接模式:经典电商支付场景

829 阅读4分钟

一:流程图分析

行为-线上线下多支付方式场景.drawio.png

{
  "orderType": "Online",       // 订单类型,表示这是一个在线订单 可选Online或者Offline
  "payment  Method": "alipay",   // 支付方式,选择支付宝作为支付方式 可选 credit_card/alipay/wechat
  "amount": 100.0              // 订单金额,表示这次订单的金额是100元
}
//注意:测试发送不能带注释
{
  "orderType": "Online",       
  "paymentMethod": "alipay",  
  "amount": 100.0             
}

二:具体代码讲解

要实现一个电商业务的复杂示例,结合策略模式(Strategy Pattern)和桥接模式(Bridge Pattern),我们可以通过 Spring Boot 来构建一个 RESTful API。以下是这个实现的概述和代码示例:

  • 策略模式 用于选择不同的支付方式(如信用卡支付、支付宝支付、微信支付等)。
  • 桥接模式 用于将支付方式与电商系统的订单处理进行解耦,可以扩展其他支付方式和订单系统,而不需要修改现有代码。

需求设计

我们假设电商系统需要:

  1. 不同的支付方式,每种支付方式有不同的支付策略。
  2. 电商平台支持不同的订单处理方式,比如“线上支付订单”与“线下支付订单”需要做不同的处理。
  3. 支持RESTful接口来测试这些功能。

设计结构

  1. 支付策略接口(PaymentStrategy) - 定义支付策略的通用接口。
  2. 具体支付策略(如 CreditCardPayment, AlipayPayment) - 实现不同的支付方式。
  3. 订单处理接口(OrderProcessor) - 定义订单处理的通用接口。
  4. 具体订单处理方式(如 OnlineOrderProcessor, OfflineOrderProcessor) - 根据支付方式和订单类型进行处理。
  5. 桥接模式的应用:订单处理的实现与支付方式实现分离。

代码实现

  1. Maven依赖

首先,确保 pom.xml 包含 Spring Boot 的依赖以及必要的 Jackson 序列化支持:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
    </dependency>
</dependencies>

2. 支付策略接口和具体实现

package com.xiaoyongcai.io.designmode.Service.Strategy;
​
public interface PaymentStrategy {
    void pay(double amount);
}
​
package com.xiaoyongcai.io.designmode.Service.Strategy.Impl;
​
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import org.springframework.stereotype.Service;
​
@Service
public class AlipayPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付完成,消费"+amount+"元。支付方式为:支付宝");
    }
}
package com.xiaoyongcai.io.designmode.Service.Strategy.Impl;
​
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import org.springframework.stereotype.Service;
​
@Service
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付完成,消费"+amount+"元。支付方式为:信用卡");
    }
}
package com.xiaoyongcai.io.designmode.Service.Strategy.Impl;
​
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import org.springframework.stereotype.Service;
​
@Service
public class WeChatPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付完成,消费"+amount+"元。支付方式为:微信支付");
    }
}
​
​

3. 订单处理接口和具体实现

package com.xiaoyongcai.io.designmode.Service.BridgePattern;
​
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
​
public interface OrderProcessor {
    void processOrder(double amount);
    void setPaymentStrategy(PaymentStrategy paymentStrategy);
}
​
package com.xiaoyongcai.io.designmode.Service.BridgePattern.Impl;
​
import com.xiaoyongcai.io.designmode.Service.BridgePattern.OrderProcessor;
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import lombok.Data;
import org.springframework.stereotype.Service;
@Data
@Service
public class OnlineOrderProcessor implements OrderProcessor {
    private  PaymentStrategy paymentStrategy;
​
​
    @Override
    public void processOrder(double amount) {
        System.out.println("尽管你正在使用某种特定的支付方式,但是此时要注意:你是通过线上访问桥接到该支付请求的哦");
        paymentStrategy.pay(amount);
    }
​
    @Override
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
}
package com.xiaoyongcai.io.designmode.Service.BridgePattern.Impl;
​
import com.xiaoyongcai.io.designmode.Service.BridgePattern.OrderProcessor;
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import org.springframework.stereotype.Service;
​
@Service
public class OfflineOrderProcessor implements OrderProcessor {
    private  PaymentStrategy paymentStrategy;
​
​
​
    @Override
    public void processOrder(double amount) {
        System.out.println("尽管你正在使用某种特定的支付方式,但是此时要注意:你是通过线下访问桥接到该支付请求的哦");
        paymentStrategy.pay(amount);
    }
​
    @Override
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
}
​
​
​

4. 订单服务

在这个服务中,使用桥接模式将支付方式与订单处理解耦。

package com.xiaoyongcai.io.designmode.Service.BridgePattern;
​
import com.xiaoyongcai.io.designmode.Service.BridgePattern.Impl.OfflineOrderProcessor;
import com.xiaoyongcai.io.designmode.Service.BridgePattern.Impl.OnlineOrderProcessor;
import com.xiaoyongcai.io.designmode.Service.Strategy.Impl.AlipayPayment;
import com.xiaoyongcai.io.designmode.Service.Strategy.Impl.CreditCardPayment;
import com.xiaoyongcai.io.designmode.Service.Strategy.Impl.WeChatPayment;
import com.xiaoyongcai.io.designmode.Service.Strategy.PaymentStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.HashMap;
import java.util.List;
import java.util.Map;
​
@Service
public class OrderService {
    private final Map<String, OrderProcessor> orderProcessorMap;
​
    @Autowired
    public OrderService(List<OrderProcessor> orderProcessors) {
        orderProcessorMap = new HashMap<>();
        for (OrderProcessor orderProcessor : orderProcessors) {
            if (orderProcessor instanceof OnlineOrderProcessor) {
                orderProcessorMap.put("Online", orderProcessor);
            } else if (orderProcessor instanceof OfflineOrderProcessor) {
                orderProcessorMap.put("Offline", orderProcessor);
            }
        }
    }
​
    public void processOrder(String orderType, String paymentMethod, double amount) {
        // 获取对应的 OrderProcessor
        OrderProcessor processor = orderProcessorMap.get(orderType);
        if (processor == null) {
            throw new IllegalArgumentException("注意:你的订单类型无效,请确认是否为Online或者Offline: " + orderType);
        }
​
        // 根据传入的支付方式选择支付策略
        PaymentStrategy paymentStrategy = choosePaymentStrategy(paymentMethod);
​
        // 将选择的支付策略注入到处理器中
        processor.setPaymentStrategy(paymentStrategy);
​
        // 执行订单处理逻辑
        processor.processOrder(amount);
    }
​
    // 动态选择支付策略的逻辑
    private PaymentStrategy choosePaymentStrategy(String paymentMethod) {
        switch (paymentMethod) {
            case "credit_card":
                return new CreditCardPayment();
            case "alipay":
                return new AlipayPayment();
            case "wechat":
                return new WeChatPayment();
            default:
                throw new IllegalArgumentException("前端传入的支付方式请求出错/请检查是否为credit_card, alipay, wechat: " + paymentMethod);
        }
    }
}
​

5. Controller

package com.xiaoyongcai.io.designmode.Controller.ChainOfResponsibility;
​
import com.xiaoyongcai.io.designmode.Service.ChainOfResponsibility.RequestProcessor;
import com.xiaoyongcai.io.designmode.pojo.ChainOfResponsibility.Request;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
@RequestMapping("/api")
public class RequestController {
​
    private final RequestProcessor requestProcessor;
​
    public RequestController(RequestProcessor requestProcessor) {
        this.requestProcessor = requestProcessor;
    }
​
    @PostMapping("/validateRequest")
    public String validateRequest(@RequestBody Request request) {
        boolean result = requestProcessor.processRequest(request);
        return result ? "Request processed successfully" : "Request validation failed";
    }
}
​

6.RequestPOJO

package com.xiaoyongcai.io.designmode.pojo.ChainOfResponsibility;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
​
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Request {
    private boolean loggedIn;
    private boolean hasPermission;
    private boolean valid;
    public boolean isLoggedIn(){
        return loggedIn;
    }
​
    public boolean hasPermission(){
        return hasPermission;
    }
​
    public boolean isValid(){
        return valid;
    }
}
​

测试流程

你可以通过 Postman 或者 cURL 测试这个系统:

请求示例

  • 创建一个线上订单,使用支付宝支付:

    POST http://localhost:8080/order/create?orderType=online&paymentMethod=alipay&amount=100.0
    
  • 创建一个线下订单,使用微信支付:

    POST http://localhost:8080/order/create?orderType=offline&paymentMethod=wechat&amount=50.0
    
  • 创建一个线上订单,使用信用卡支付:

    POST http://localhost:8080/order/create?orderType=online&paymentMethod=credit_card&amount=200.0