【问题标题】:Java - Generic for Payment processing with Strategy patternJava - 具有策略模式的支付处理的泛型
【发布时间】:2022-01-19 23:14:39
【问题描述】:

我正在尝试在基于 Spring webflux 的应用程序中实现用于支付处理的策略模式方法。

我的应用程序支持多种支付方式,如卡支付、现金支付…… 此外,我们必须支持 Square & Stripe 卡支付。

模型类,

// Model interface
public interface PaymentModel {

}

// Base model with attributes needed for all payment types
public class BaseModel implements PaymentModel {

    private Float amount;
    private Integer userId;
}

public class SquareCardModel extends BaseModel {

    private String merchantId;
    private String device;
    private String orderId;

}

public class StripeCardModel extends BaseModel {

    private String merchantId;
    private String orderId;

}

public class CashModel extends BaseModel {

    private String name;
    private String orderId;

}

服务类,

@Service
public interface PaymentService<T extends PaymentModel> {

    Mono<ServerResponse> pay(T model);

    String method();
}

@Service
public class CashPaymentService implements PaymentService<CashModel> {

    private static final String PAYMENT_METHOD = "cash";

    @Override
    public Mono<ServerResponse> pay(CashModel model) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String method() {
        return PAYMENT_METHOD;
    }

}

@Service
public class SquarePaymentService implements PaymentService<SquareCardModel> {

    private static final String PAYMENT_METHOD = "cash";

    @Override
    public Mono<ServerResponse> pay(SquareCardModel model) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String method() {
        return PAYMENT_METHOD;
    }

}

@Service
public class StripePaymentService implements PaymentService<StripeCardModel> {

    private static final String PAYMENT_METHOD = "cash";

    @Override
    public Mono<ServerResponse> pay(SquareCardModel model) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String method() {
        return PAYMENT_METHOD;
    }

}

工厂类,

@Service
public class PaymentFactory<T> {

    private final List<PaymentService<? extends PaymentModel>> paymentServices;

    @Autowired
    public PaymentFactory(List<PaymentService<? extends PaymentModel>> paymentServices) {
        this.paymentServices = paymentServices;
    }

    public PaymentService<? extends PaymentModel> retrievePaymentService(final String paymentMethod) {
        Optional<PaymentService<? extends PaymentModel>> paymentService = paymentServices.stream()
                .filter(service -> service.method().equals(paymentMethod)).findFirst();

        if (paymentService.isEmpty()) {
            throw new IllegalArgumentException("Unsupported Payment method ");
        }
        return paymentService.get();
    }

}

用户选择支付方式,调用到后台,

@Transactional
    public Mono<ServerResponse> payBilling(ServerRequest request) {
            return request.bodyToMono(PaymentDto.class).flatMap(paymentReq -> {
                if (paymentReq.getPaymentType().equals("CC")) { // For Card
                    return processCardPayment(usr, paymentReq);
                } else {
                    return badRequest().bodyValue("Not supported yet !");
                }
            });
    }

private Mono<? extends ServerResponse> processCardPayment(
            PaymentDto paymentReq) {
            PaymentService<PaymentModel> paymentService = (PaymentService<PaymentModel>) paymentFactory
                    .retrievePaymentService(paymentReq.getPaymentType());
            PaymentModel paymentModel = buildPaymentModel((String) paymentReq.getPaymentType(), paymentReq,
                    jsonMap);
            return paymentService.pay(paymentModel);
    }

    private PaymentModel buildPaymentModel(final String paymentMethod, final PaymentDto paymentReq,
        if (paymentMethod.equals("squarePayment")) {
            SquareCardModel model = new SquareCardModel();
            model.setAmount(paymentReq.getTotal());
            model.setMerchantId(paymentReq.getMerchantid());
            model.setOrderId(orderId);

            return model;
        }

        return null;

    }

问题:

  1. 不确定我是否使用策略模式正确实现了泛型。
  2. 另外,我不喜欢这里的类型转换。 (支付服务)。有没有更好的方法?
  3. 为什么我还需要使用 if 来创建不同的模型。

if (paymentMethod.equals("squarePayment")) {

PaymentService<PaymentModel> paymentService = (PaymentService<PaymentModel>) paymentFactory
                        .retrievePaymentService(paymentReq.getPaymentType());
                PaymentModel paymentModel = buildPaymentModel((String) paymentReq.getPaymentType(), paymentReq,
                        jsonMap);
                return paymentService.pay(paymentModel);

【问题讨论】:

  • 你没有显示retrievePaymentService的代码。
  • @tgdavies 抱歉打错了。它在工厂类中。
  • Float amount;?哦。不好了。没有没有。
  • @rzwitserloot 有什么建议? BigDecimal ... 我们仅支持 2 位十进制数字,例如 1000.25 或 80.74 .... 金额不会超过 10K
  • PaymentFactory(应该命名为PaymentServiceFactory)似乎不需要有类型参数。

标签: java generics design-patterns factory strategy-pattern


【解决方案1】:

从类型的角度来看,这是您的代码的简化版本,我认为它可以维护您需要做的事情:

import java.util.Optional;

public class App {

    public interface PaymentModel { }

    public static class CashModel implements PaymentModel { }

    public interface PaymentService<T extends PaymentModel> {
        void pay(T model);
        void pay2(PaymentModel model);
    }

    public static class PaymentFactory {
        public PaymentService<PaymentModel> retrievePaymentService(final String paymentMethod) {
            Optional<PaymentService<PaymentModel>> paymentService = null;
            return paymentService.get();
        }
        public PaymentService<? extends PaymentModel> retrievePaymentService2(final String paymentMethod) {
            Optional<PaymentService<PaymentModel>> paymentService = null;
            return paymentService.get();
        }
    }

    public static void main(String... args) throws NoSuchFieldException, IllegalAccessException {
        PaymentFactory paymentFactory = null;
        PaymentService<PaymentModel> paymentService = paymentFactory
                .retrievePaymentService("foo");
        paymentService.pay(new CashModel());
        
        PaymentService<? extends PaymentModel> paymentService2 = paymentFactory
                .retrievePaymentService2("foo");
        paymentService2.pay(new CashModel()); // error
        paymentService2.pay2(new CashModel()); // ok
    }
}

看看retrievePaymentServiceretrievePaymentService2的区别。

retrievePaymentService 返回PaymentService&lt;PaymentModel&gt;,表示它是一种适用于任何PaymentModel 实现的支付服务。 retrievePaymentService2 返回 PaymentService&lt;? extends PaymentModel&gt;,表示它是一种支付服务,适用于某些特定的、未知的 PaymentModel 实现。

由于您已经确保您的 PaymentModel 类型与您从工厂获得的 PaymentService 匹配,所以第一个表单就是您想要的。

更好的设计可能会尝试有两个需要在运行时仔细匹配的并行类层次结构。

另外,processCardPayment 似乎应该处理所有PaymentModels?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多