Let's assume we have a simple payment feature on an online shop. We want to manage different transactions with different processors of transactions:
So we have the following classes:
class PaymentTransaction implements Transaction {
}
class RefundTransaction implements Transaction {
}
class PaypalProcessor implements Processor {
}
class PayplugProcessor implements Processor {
}
As suggested in this answer, we could use the following class which uses Strategy and polymorphism.
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);
}
}
We assume the processor and the transaction to use are given from the database. I wonder how to create the PaymentProcessor object.
It seems that an abstract factory class with only one method is still a valid Abstract Factory pattern. So, in this case I wonder if using Abstract Factory would be relevant.
PaymentProcessorFactory class to create PaymentProcessor with his two attributes according the details given from the database?What is a best practice to use a factory in this case?
We assume the processor and the transaction to use are given from the database. I wonder how to create the PaymentProcessor object.
I would define an interface that I can adapt to the database result or any other source that can provide the data needed to create a PaymentProcessor. This is also useful for unittests.
public interface PaymentProcessorFactoryArgs {
String getProcessorType();
String getTransactionType();
}
and then implement a factory like this.
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);
}
}
This is just a quick example. It would be better if you can register Processors and Transactions. E.g.
public void register(String processorType, Processor processor){
...
}
public void register(String transactionType, Transaction transaction){
...
}
You also might want to use anther type then String for the keys, maybe an enum.
In this example the Processor and Transaction objects are re-used every time a PaymentProcessor is created. If you want to create new objects for each PaymentProcessor, you can replace the Maps type
private Map<String, Factory<Processor>> processorMap = new HashMap<>();
private Map<String, Factory<Transaction>> transactionMap = new HashMap<>();
with anther factory interface. E.g.
public interface Factory<T> {
public T newInstance();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With