The Strategy Design Pattern is a Behavioral Design Pattern that enables selecting an algorithm’s behavior at runtime. Instead of implementing a single algorithm directly, run-time instructions specify which of a family of algorithms to use.
This pattern is ideal when you need to switch between different algorithms or actions in an object dynamically. That means the Strategy Design Pattern is used when we have multiple algorithms (solutions) for a specific task, and the client decides which algorithm to use at runtime.
Components of Strategy Design Pattern
- Strategy Interface: This defines a set of methods that represent the algorithms. It acts as a contract for all concrete strategy classes.
- Concrete Strategies: These are the actual implementations of the algorithms defined in the strategy interface.
- Context: This is the class that uses the strategy. It contains a reference to the strategy interface and can switch between different strategies dynamically.
Example in C#
Let's consider a scenario where we have a payment processing system that supports multiple payment methods: Credit Card, PayPal, and Bitcoin. We can use the Strategy Pattern to implement these payment methods interchangeably.
Create Strategy Interface (IPaymentStrategy.cs)namespace StrategyPattern.Strategy { /// <summary> /// Define the strategy interface /// </summary> public interface IPaymentStrategy { void ProcessPayment(double amount); } }
- CreditCardPaymentStrategy.cs
namespace StrategyPattern.Strategy { /// <summary> /// Implement concrete strategies /// </summary> public class CreditCardPaymentStrategy : IPaymentStrategy { public void ProcessPayment(double amount) { Console.WriteLine($"Processing credit card payment of ${amount}"); // Logic to process credit card payment } } }
- PayPalPaymentStrategy.cs
namespace StrategyPattern.Strategy { /// <summary> /// Implement concrete strategies /// </summary> public class PayPalPaymentStrategy : IPaymentStrategy { public void ProcessPayment(double amount) { Console.WriteLine($"Processing PayPal payment of ${amount}"); // Logic to process PayPal payment } } }
- BitcoinPaymentStrategy.cs
namespace StrategyPattern.Strategy { public class BitcoinPaymentStrategy : IPaymentStrategy { /// <summary> /// Implement concrete strategies /// </summary> public void ProcessPayment(double amount) { Console.WriteLine($"Processing Bitcoin payment of ${amount}"); // Logic to process Bitcoin payment } } }
using StrategyPattern.Strategy; namespace StrategyPattern.Context { /// <summary> /// Implement the context /// </summary> public class PaymentProcessor { private IPaymentStrategy _paymentStrategy; public PaymentProcessor(IPaymentStrategy paymentStrategy) { _paymentStrategy = paymentStrategy; } public void ProcessPayment(double amount) { _paymentStrategy.ProcessPayment(amount); } // Method to dynamically change the payment strategy public void ChangePaymentStrategy(IPaymentStrategy newPaymentStrategy) { _paymentStrategy = newPaymentStrategy; } } }
// Create payment processor with a default strategy using StrategyPattern.Context; using StrategyPattern.Strategy; var paymentProcessor = new PaymentProcessor(new CreditCardPaymentStrategy()); // Process payments using different strategies paymentProcessor.ProcessPayment(100.0); paymentProcessor.ChangePaymentStrategy(new PayPalPaymentStrategy()); paymentProcessor.ProcessPayment(50.0); paymentProcessor.ChangePaymentStrategy(new BitcoinPaymentStrategy()); paymentProcessor.ProcessPayment(200.0); Console.ReadLine();
Output
In this example, we have defined a strategy interface IPaymentStrategy with a method ProcessPayment. Concrete strategies like CreditCardPaymentStrategy, PayPalPaymentStrategy, and BitcoinPaymentStrategy implement this interface with their own payment processing logic. The PaymentProcessor class acts as a context, allowing clients to switch between different payment strategies dynamically.
The full source code is available here:
Conclusion
The Strategy Design Pattern promotes code reuse, flexibility, and maintainability by encapsulating algorithms in separate classes and enabling them to vary independently. It's particularly useful when you have multiple algorithms that need to be interchangeable at runtime.
Happy coding!! 😊
No comments:
Post a Comment