I am writing a payment Processor class, then will take different payment objects in input and talks to external services to process payment.My class is designed using polymorphism as follow:

public class PaymentProcessor

DebitCardTransactionDetails processPayment(DebitCard);
CreditCardTransactionDetails processPayment(CreditCard)
NetBankingTransactionDetails processPayment(NetBanking)

I am using same name,so that client dont have to worry about selecting the method based on paymentType using if-else,If I keep all api name different, then the client has to do if-else and select api to call.Here Client can call processPayment() api and get the work done.Any downsides for this?I cannot think though.


This approach uses overloading, i.e. having several functions with the same name but with different argument types.

It’s not true polymorphism: it works only if the type of the payment details (e.g. DebitCard, CreditCard, ...) are known at compile time.

Your app will then needs to foresee different code for handling each type. Typically, you’d end with:

 if (...) { 
  } else if (...) {
   } else ....

This leads to a lot of redundant boilerplate code and is difficult to maintain if you’d add a new payment method (e.g. BitCoinWallet or PayPalDetail)

To do it right, abstract on the payment details. Create a general interface, e.g. IPaymentDetail that your payment processor needs. Make CreditCard, DebitCard etc... be implementations of IPaymentDetail. Same for the transaction details and use:

public class PaymentProcessor
ITransactionDetail processPayment(IPaymentDetail);
  • But IPaymentDetail cannot be implemented by CreditCard,DebitCard etc. because these contains entirely different data.At high level these may be payment methods, but internally these are different things all together.Also even if somehow I manage to do this. Then at processPaymentDetail,I have to use if -else to see what is the type of the IPaymentDetail as If it is creditCard then call creditCard external Service and so on. – user124 Mar 21 at 13:45
  • @user124 I just started the idea on how to bring true polymorphism into that. But you’re right: it will not be sufficient since payment processing shall be done by the payment processor and not by the credit card. There are chances that more objects will have to be involved to properly separate concerns and still allow for polymorphism (at least an IPaymentService) – Christophe Mar 21 at 13:56
  • I definitely need to have the api in paymentProcessor class for each type of payment. Whether they can be of same name or different , i think it does not matter,as at the client side, it should have similar 4-5 api where each api will receive its own input and then pass to payment processor.and the client cannot escape this logic, because if 4 clients use this,all of them have to use that 4-5 if -else, because these are different functionality they are trying to achieve and each functionality is a behaviour and hence an different api.What do you think? – user124 Mar 21 at 14:05

I assume you want to abstract over payment methods, like "CreditCard", "DebitCard", etc., not payment processors (companies) each of which can handle all or some of those methods.

If that is the case, and you want to achieve "decoupling", i.e. you want to have all logic pertaining to a method in one place, you'll have to transfer control to that implementation.

What I mean by that, is now you're trying to micro-manage the implementation, trying to figure out some generic form of a data container that would work. That will not work. Each payment method will have quirks, and you'll have to add special handling to the user code or to the UI to execute it.

The only way to actually "handle" each payment method completely generically, is to not control them, but let them control the whole process. This means, depending on the application, letting them show screens to the user, implement their own workflow, etc.

Something like PaymentMethods.startPayment(): UIComponent. Which after a selection of method would delegate to PaymentMethod.processPayment(): UIComponent, or something similar. Anything else would expose names, quirks, workflow details, which would in the end not allow you to introduce a new payment method with polymorphism only.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.