2017-01-30 24 views
2

Предположим, у нас есть простая функция оплаты в интернет-магазине. Мы хотим управлять различными транзакциями с различными обработчиками транзакций:Как использовать фабрику для создания объектов, которые используют шаблон стратегии?

  • Сделка может быть оплатой или возвратом.
  • Процессором транзакций может быть Paypal или Payplug.

Итак, мы имеем следующие классы:

class PaymentTransaction implements Transaction { 

} 

class RefundTransaction implements Transaction { 

} 

class PaypalProcessor implements Processor { 

} 

class PayplugProcessor implements Processor { 

} 

Как было предложено в this answer, мы могли бы использовать следующий класс, который использует стратегию и полиморфизм.

class PaymentProcessor { 
    private Processor processor; 
    private Transaction transaction; 

    public PaymentProcessor(Processor processor, Transaction transaction) { 
      this.processor = processor; 
      this.transaction = transaction; 
    } 

    public void processPayment() { 
     processor.process(transaction); 
    } 
} 

Мы предполагаем, что процессор и транзакция будут использованы из базы данных. Интересно, как создать объект PaymentProcessor.

Похоже, что абстрактный заводский класс только с одним методом по-прежнему действителен Abstract Factory pattern. Итак, в этом случае я задаюсь вопросом, применимо ли использование Abstract Factory.

  • Если да, то как его реализовать?
  • Если нет, следует ли использовать метод Factory Method с классом PaymentProcessorFactory для создания PaymentProcessor с его двумя атрибутами в соответствии с данными из базы данных?

Какая практика использования фабрики в этом случае?

ответ

2

Мы предполагаем, что процессор и транзакцию для использования приведено в базы данных. Интересно, как создать объект PaymentProcessor.

Я бы определил интерфейс, который я могу адаптировать к результату базы данных или любому другому источнику, который может предоставить данные, необходимые для создания PaymentProcessor. Это также полезно для unittests.

public interface PaymentProcessorFactoryArgs { 
    String getProcessorType(); 
    String getTransactionType(); 
} 

, а затем реализовать такую ​​фабрику.

public class PaymentProcessorFactory { 

    private Map<String, Processor> processorMap = new HashMap<>(); 
    private Map<String, Transaction> transactionMap = new HashMap<>(); 

    public PaymentProcessorFactory() { 
    processorMap.put("paypal", new PaypalProcessor()); 
    processorMap.put("payplug", new PayplugProcessor()); 

    transactionMap.put("refund", new RefundTransaction()); 
    transactionMap.put("payment", new PaymentTransaction()); 
    } 

    public PaymentProcessor create(PaymentProcessorFactoryArgs factoryArgs) { 
    String processorType = factoryArgs.getProcessorType(); 
    Processor processor = processorMap.get(processorType); 
    if(processor == null){ 
     throw new IllegalArgumentException("Unknown processor type " + processorType); 
    } 

    String transactionType = factoryArgs.getTransactionType(); 
    Transaction transaction = transactionMap.get(transactionType); 
    if(transaction == null){ 
     throw new IllegalArgumentException("Unknown transaction type " + processorType); 
    } 

    return new PaymentProcessor(processor, transaction); 
    } 
} 

Это просто быстрый пример. Было бы лучше, если бы вы могли зарегистрировать Processor s и Transaction s. Например.

public void register(String processorType, Processor processor){ 
    ... 
} 
public void register(String transactionType, Transaction transaction){ 
    ... 
} 

Вы также можете использовать пыльники типа, то String для ключей, возможно перечисления.

В этом примере объекты Processor и Transaction повторно используются каждый раз, когда создается PaymentProcessor. Если вы хотите, чтобы создать новые объекты для каждого PaymentProcessor, вы можете заменить Map ы типа

private Map<String, Factory<Processor>> processorMap = new HashMap<>(); 
private Map<String, Factory<Transaction>> transactionMap = new HashMap<>(); 

с пыльников фабричного интерфейса. Например.

public interface Factory<T> { 
    public T newInstance(); 
} 
+0

Если я не ошибаюсь, это реализация шаблона _Factory Method_, верно? – Kwadz

2

Возможно, вы можете использовать шаблон строителя. В шаблоне строителя есть класс, называемый режиссером, который знает алгоритм создания сложного объекта. Для создания компонентов сложный объект, построенный директором, использует построитель. Подобно этому вы можете изменить определенные компоненты для создания всего сложного объекта.

В вашем случае PaymentProcessor (сложный объект) состоит из Платежа и Процессора, поэтому алгоритм должен вводить их в PaymentProcessor. Строитель должен строить детали. Чтобы создать комбинацию PayPal-возврат, вы должны создать строитель, который возвращает PaypalProcessor и RefundTransaction. Когда вы хотите создать payplug-платеж, строитель должен вернуть PaymentTransaction и PayPlugProcessor.

public interface PaymentProcessorBuilder { 
    public Transaction buildTransaction(); 
    public Processor buildProcessor(); 
} 

public class PaypalRefundProcessorBuilder implements PaymentProcessorBuilder { 
    public Transaction buildTransaction { 
     return new RefundTransaction(); 
    } 
    public Processor buildProcessor { 
     return new PayPalProcessor(); 
    } 
} 

public class PayPlugPaymentProcessorBuilder implements PaymentProcessorBuilder { 
    public Transaction buildTransaction { 
     return PaymentTransaction(); 
    } 
    public Processor buildProcessor { 
     return new PayPlugProcessor(); 
    } 
} 

Теперь директор может использовать строитель составить PaymentProcessor:

publi PaymentProcessorDirector { 
    public PaymentProcessor createPaymentProcessor(PaymentProcessorBuilder builder) { 
     PaymentProcessor paymentProcessor = new PaymentProcessor(); 

     paymentProcessor.setTransaction(builder.buildTransaction()); 
     paymentProcessor.setProcessor(builder.buildProcessor()); 

     return paymentProcessor; 
    } 
} 

Теперь Созданное PaymentProcessor зависит от пройденного Builder:

... 
PaymentProcessorDirector director = new PaymentProcessorDirector(); 
PaymentProcessorBuilder builder = new PaypalRefundProcessorBuilder(); 

PaymentProcessor paymentProcessor = director.createPaymentProcessor(builder); 
... 

Для каждой комбинации вы можете создать строитель. Если вы передадите правильному строителю директору, вы снова получите требуемый PaymentProcessor.

Теперь вопрос, как вы можете получить правильный строитель.Поэтому вы можете использовать фабрику, которая принимает некоторые аргументы событий и решает, какой строитель должен быть создан. Этот строитель вы передаете директору и получите желаемый платежный процессор.

ВНИМАНИЕ: Это единственное возможное решение этой проблемы. У каждого решения есть преимущества и недостатки. Чтобы найти правильное решение, вы должны балансировать хорошие и плохие вещи.

PS: Надеюсь, что синтаксис верен. Я не разработчик Java.

EDIT: Вы можете интерпретируете директор картины строителя как PaymentProcessorFactory с самим застройщиком в качестве стратегии для построения части PaymentProcessor