Reputation: 1
Objective: I want to implement multiple Payment Processors. (Language: C#)
Design Choice: I chose the Strategy Pattern. It helped in calling the appropriate payment processor.
Problem: Different payment processor returns different responses. I had to create seperate Process() method per Processor.
I tried to unify all the response in a single interface but the interface has so many properties and I'm not sure if there is a better way.
public class PaymentStrategy
{
public static IPaymentProcessor GetPaymentType(IPaymentDetails paymentDetails)
{
if (paymentDetails.PaymentType == PaymentTypes.PaymentProcessorA)
return new PaymentProcessorA();
else if (paymentDetails.PaymentType == PaymentTypes.PaymentProcessorA)
return new PaymentProcessorA();
else if (paymentDetails.PaymentType == PaymentTypes.PayPal)
return new PayPal();
else
throw new NotImplementedException();
}
}
public class PaymentService : IPaymentService
{
public IPaymentDetails PaymentDetails { get; set; }
public IPaymentProcessor PaymentProcessor { get; set; }
public PaymentService(IPaymentDetails paymentDetails)
{
PaymentDetails = paymentDetails;
PaymentProcessor = PaymentStrategy.GetPaymentType(paymentDetails);
}
public PaymentA_Response Process_A()
{
return PaymentProcessor.Process_A(PaymentDetails);
}
public PaymentB_Response Process_B()
{
return PaymentProcessor.Process_B(PaymentDetails);
}
}
internal class PaymentProcessorA : IPaymentProcessor
{
public string GetPaymentGatewayName()
{
return this.GetType().Name;
}
public PaymentA_Response Process(IPaymentDetails paymentDetails)
{
return new PaymentA_Response() { TxId = 1, ResponseFromA = $"Success from {GetType().Name}" };
}
}
internal class PaymentProcessorB : IPaymentProcessor
{
public string GetPaymentGatewayName()
{
return this.GetType().Name;
}
public PaymentB_Response Process(IPaymentDetails paymentDetails)
{
return new PaymentB_Response() { TxId = 1, ResponseFromB = $"Success from {GetType().Name}" };
}
}
class PaymentA_Response
{
public int TransactionId { get; set; }
public string Status { get; set; }
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public string E { get; set; }
}
class PaymentB_Response
{
public int Tx { get; set; }
public string Status { get; set; }
public string F { get; set; }
public string G { get; set; }
public string H { get; set; }
public string I { get; set; }
public string J { get; set; }
}
class Program
{
static void Main(string[] args)
{
TestPaymentGateway();
Console.ReadLine();
}
private static void TestPaymentGateway()
{
// Calling code for PaymentGateway A
IPaymentDetails paymentDetails = new PaymentDetails()
{
Amount = 10,
PaymentType = PaymentTypes.PaymentProcessorA
};
PaymentService paymentService = new PaymentService(paymentDetails);
Process_A_Response resopnse = paymentService.Process_A();
Console.WriteLine(resopnse.A);
// Calling code for PaymentGateway B
IPaymentDetails paymentDetails = new PaymentDetails()
{
Amount = 10,
PaymentType = PaymentTypes.PaymentProcessorB
};
PaymentService paymentService = new PaymentService(paymentDetails);
Process_B_Response resopnse = paymentService.Process_B();
Console.WriteLine(resopnse.F);
}
}
Solution Needed: I want the client code to call a method named Process() using PaymentService class that returns a single response object instead of calling process_A or Process_B.
Upvotes: 0
Views: 959
Reputation: 62488
You can have generic interface in place to handle it so that one Process
method can handle it :
public class PaymentService<TResponse> : IPaymentService<TResponse>
{
public IPaymentDetails PaymentDetails { get; set; }
public IPaymentProcessor PaymentProcessor { get; set; }
public PaymentService(IPaymentDetails paymentDetails)
{
PaymentDetails = paymentDetails;
PaymentProcessor = PaymentStrategy.GetPaymentType(paymentDetails);
}
public TResponse Process()
{
return PaymentProcessor.Process(PaymentDetails);
}
}
and on calling side you will need to specify the response type:
var service = new PaymentService<PaymentA_Response>();
var response = service.Process();
The above snippet is just to give idea how you can use generic type parameter to incorporate it using one method in service. You might need changes at other places as well.
Upvotes: 1