mardi 17 octobre 2023

How to conditionally select concrete implementation for strategy pattern using Dependency Injection C#

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?

Aucun commentaire:

Enregistrer un commentaire