I am trying to understand the Strategy Pattern in order to utilise it for a problem I have.
The current code looks as such where I have an amount that I want to process based on a payment type.
public class PaymentProcessor { private PaymentType paymentType; public void processPayment(double amount) { if (paymentType == PaymentType.CREDIT_CARD) { Console.Writeline("Processing credit card payment of amount " + amount); } else if (paymentType == PaymentType.DEBIT_CARD) { Console.Writeline("Processing debit card payment of amount " + amount); } else if (paymentType == PaymentType.PAYPAL) { Console.Writeline("Processing PayPal payment of amount " + amount); } else { throw Exception(); } } public void setPaymentType(PaymentType paymentType) { this.paymentType = paymentType; } } enum PaymentType { CREDIT_CARD, DEBIT_CARD, PAYPAL } So based on the strategy pattern I would need to create an interface for all payments
public interface IPaymentStrategy { void processPayment(double amount); } then i need to create concrete implemtations for each class I will only give an example of one but you get the idea.
public class CreditCardPaymentStrategy : IPaymentStrategy { public void processPayment(double amount) { Console.Writeline("Processing credit card payment of amount " + amount); } } So all the payment strategies will have a concrete implemntation like above.
Finally using Dependency injection and Dependency Inversion I refactor the payment processor to look like this
public class PaymentProcessor { private PaymentStrategy paymentStrategy; public PaymentProcessor(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void processPayment(double amount) { paymentStrategy.processPayment(amount); } } But heres the bit im missing. Where and how do I implement the conditional logic to select the correct concrete implementation to register against the payment strategy based on a payment type?
I have tried looking online. All the examples I see seem to have another class like a factory that news up the concrete version and passes it into the interface. But Im not sure thats the right way to do it as i dont feel like I should be newing up classes that arent POCOS as my DI container should be doing that. So what am I missing in the strategy to conditionally select the concrete type based on the Payment type? Am i even using the right pattern here as i have seen people compare the strategy pattern to Depedency injection. If thats the cose what pattern is better for the conditional selection rather than registering a concrete class with the interface and having to manually change it in the registration every time I want to use a different payment strategy, but be able to switch between strategies at runtime?