Я думаю, что у вас есть различные способы сделать это.
Один из них будет следующим.
Я вижу, что PaymentGateway
это private final
, который заставляет вас используйте инъекцию в конструктор, даже если вы поместите @Autowired
поверх поля члена. Это означает, что вы можете создать свой PaymentService
как bean-компонент следующим образом:
@Bean
public PaymentService paymentService(PaymentGateway gw) {
return new PaymentService(gw);
}
и здесь вы можете позволить своему клиенту использовать то, что хочет реализация PaymentGateway
.
РЕДАКТИРОВАТЬ
Эта более поздняя редакция предназначена для того, чтобы ввести Dispatcher
для поиска правильного PaymentGateway
компонента.
Прежде всего, введите тип перечисления, скажем так
enum PmtGatewayType {
PayPal,
Stripe,
Square
}
Теперь, в интерфейсе PaymentGateway
добавьте метод, подобный следующему:
public boolean accept(PmtGatewayType pmtGatewayType);
и реализуйте его следующим образом:
class Stripe implements PaymentGateway {
private PmtGatewayType gwType;
@Override
public boolean accept(PmtGatewayType pmtGwType) {
return gwType.equals(pmtGwType);
}
Теперь вы можете создать еще один класс с именем PmtGwDispatcher
, в который вы будете вводить List
всех PaymentGateway
бинов, например, следующий:
@Component
class PmtGwDispacher {
@Autowired
private List<PaymentGateway> pmtGateways;
public PaymentGateway select(PmtGatewayType gwType) {
PaymentGateway gw = pmtGateways.stream().filter(gw -> gw.accept(gwType)).findFirst().get();
if(gw == null) {
throw new IllegalArgumentException("The provided gateway type is invalid");
}
}
Теперь в PaymentService
вы Можно ввести PmtGwDispatcher
и использовать его.
Решение немного сложное, но оно соблюдает принципы SOLID. Каждый компонент уважает SRP, и каждый раз, когда вам нужно будет добавить новый PaymentGateway
, вы должны добавить только одну запись в enum и добавить реализацию для нового шлюза.