Guice - как реализовать фабрику, которая возвращает различные реализации

допустим, у меня есть сервис под названием Guice service и вот его конструктор

public GuiceService(IPayment payment) {
    this.payment = payment;
}

и мой код использовался для его создания с помощью перечисления

IPayment payment = new PaymentFactory.create(PaymentType.Cash);
NaiveService naiveService = new NaiveService(payment);

и у меня должна была быть где-то заводская реализация. Что-то вроде этого!--5-->

public IPayment create(PaymentType paymentType) {
    IPayment cardPayment = null;
    switch (paymentType) {
        case Cash:
            cardPayment = new CashPayment(100);
            break;
        case Card:
            cardPayment = new CardPayment(10, 100);
            break;
    }
    return cardPayment;

теперь я хочу использовать Guice, и я думаю, что хочу использовать FactoryModuleBuilder.

  1. как это сделать, если у меня есть более одного внедрения IPayment.
    (например, CardPayment, CashPayment)
    Это работает для одного

    install(new FactoryModuleBuilder()
       .implement(IPayment.class, CashPayment.class)
       .build(IPaymentFactory.class));
    
  2. как реализовать конструктор ?
    это еще вам IPayment? или он получит factoryImpl, созданный Guice?

спасибо

1 ответов


ваша существующая реализация-это лучшее, что вы можете получить.

Давайте писать общие IPaymentFactory для ясности:

public interface IPaymentFactory {
  IPayment create(/* ... */);
}

таким образом, экземпляры IPaymentFactory определяют один метод, который принимает некоторое количество параметров и возвращает экземпляр IPayment. Вы могли бы написать реализацию самостоятельно, и, очевидно, у вас есть, но FactoryModuleBuilder Guice предоставляет такие реализации интерфейса, как этот автоматически. Тебе никогда не нужно определять что-нибудь еще об этом классе: Guice подключит конструктор для вас и свяжет его с IPaymentFactory, чтобы вы могли вводить экземпляры IPaymentFactory, вызовите create(...) С вашими параметрами и получить экземпляры IPayment.

похоже, что вы собираетесь на фабрику, которая принимает перечисление:

public interface IPaymentFactory {
  IPayment create(PaymentType paymentType);
}

...но учитывая, что CashPayment принимает один произвольный параметр, а CardPayment принимает два произвольных параметра, и учитывая, что выбор между ними требует сопоставления произвольному перечислению PaymentType вы не дали Guice почти достаточно информации, чтобы построить нужный объект.

Guice FactoryModuleBuilder предназначен больше для объединения параметров конструктора с зависимостями:

// Constructor:
@Inject public BitcoinPayment(
    @Assisted long value,         // varies by instance as a constructor parameter
    BitcoinService bitcoinService // passed-in dependency satisfied by Guice
    ) { /* ... */ }

// Factory interface:
public IBitcoinPaymentFactory {
  BitcoinPayment create(long value); // users don't need to know about dependencies!
}

// Factory binding...
install(new FactoryModuleBuilder().build(IBitcoinPaymentFactory.class));

// ...which lets Guice write the equivalent of:
public GeneratedBitcoinPaymentFactory implements IBitcoinPaymentFactory {
  @Inject Provider<BitcoinService> bitcoinServiceProvider;

  @Override public BitcoinPayment create(long value) {
    return new BitcoinPayment(value, bitcoinServiceProvider.get());
  }
}

С одной стороны, фабрика тупее, чем вы думаете: она просто сочетает параметры с зависимостями, чтобы получить один весь список. С другой стороны, это удобно: вы указываете список зависимостей один раз, а Guice делает остальное.

в итоге: FactoryModuleBuilder не решит вашу проблему, но это может помочь вам создать фабрики для CashPayment и CardPayment, которые вы можете затем ввести в свою ручную реализацию PaymentFactory (которая все равно должна существовать в той или иной форме).