Let's assume we have a simple payment feature on an online shop. We want to manage different transactions with different processors of transactions:
- A transaction can be a payment or a refund.
- A processor of transactions can be Paypal or Payplug.
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.
- If yes, how to implement it?
- If no, should we use Factory Method pattern with a
PaymentProcessorFactory
class to createPaymentProcessor
with his two attributes according the details given from the database?
What is a best practice to use a factory in this case?
Maybe you can use the builder pattern. In the builder pattern there is a class called the director, which knows the algorithm of creating a complex object. To create the components the complex object is build of the director uses a builder. Like this you can change specific components to build up the whole complex object.
In your case the PaymentProcessor (the complex object) is composed out of a Payment and a Processor, so the algorithm is to inject them into a PaymentProcessor. The builder should build the parts. To build a paypal-refund combination you should create a builder which returns a PaypalProcessor and a RefundTransaction. When you want to create a payplug-payment the builder should return a PaymentTransaction and a PayPlugProcessor.
Now the Director can use the builder to compose the PaymentProcessor:
The created PaymentProcessor depends now on the passed Builder:
For each combination you can create a builder. If you pass the right builder to the director you get the wanted PaymentProcessor back.
Now the question how could you get the right builder. Therefore you can use a factory, that takes some event arguments and decides then which builder has to be made. This builder you pass in the director an get the wanted PaymentProcessor.
CAUTION: This is only one possible solution for this problem. Every solution has is advantages and disadvantages. To find the right solution you to balance the good and the bad things.
PS: Hope the syntax is correct. Im not a java developer.
EDIT: You could interprete the director of the builder pattern as a PaymentProcessorFactory with the builder itself as strategy for building the parts of the PaymentProcessor
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.and then implement a factory like this.
This is just a quick example. It would be better if you can register
Processor
s andTransaction
s. E.g.You also might want to use anther type then
String
for the keys, maybe an enum.In this example the
Processor
andTransaction
objects are re-used every time aPaymentProcessor
is created. If you want to create new objects for eachPaymentProcessor
, you can replace theMap
s typewith anther factory interface. E.g.