using System;
// 1. Strategy Interface
public interface IEncryptionStrategy
{
string Encrypt(string text);
}
// 2. Concrete Strategies
public class CaesarEncryptionStrategy : IEncryptionStrategy
{
public string Encrypt(string text)
{
// Example Caesar cipher implementation
char[] result = text.ToCharArray();
for (int i = 0; i < result.Length; i++)
{
if (char.IsLetter(result[i]))
{
char baseChar = char.IsUpper(result[i]) ? 'A' : 'a';
result[i] = (char)(((result[i] + 3 - baseChar) % 26) + baseChar);
}
}
return new string(result);
}
}
public class SubstitutionEncryptionStrategy : IEncryptionStrategy
{
public string Encrypt(string text)
{
// Example substitution cipher implementation
return text.Replace('a', '*').Replace('b', '#'); // Simplified substitution
}
}
// 3. Context
public class TextEncryptor
{
private IEncryptionStrategy _strategy;
public TextEncryptor(IEncryptionStrategy strategy)
{
_strategy = strategy;
}
public void SetStrategy(IEncryptionStrategy strategy)
{
_strategy = strategy;
}
public string EncryptText(string text)
{
return _strategy.Encrypt(text);
}
}
// Client code
class Program
{
static void Main()
{
string plaintext = "Hello, World!";
TextEncryptor encryptor = new TextEncryptor(new CaesarEncryptionStrategy());
string encryptedText = encryptor.EncryptText(plaintext);
Console.WriteLine("Encrypted using Caesar cipher: " + encryptedText);
encryptor.SetStrategy(new SubstitutionEncryptionStrategy());
encryptedText = encryptor.EncryptText(plaintext);
Console.WriteLine("Encrypted using Substitution cipher: " + encryptedText);
}
}
In these examples:
In both cases, the Strategy pattern allows different algorithms (strategies) to be encapsulated in separate classes, making them interchangeable at runtime, thus promoting flexibility and maintainability in the code.
This pattern is especially useful in situations where you want to support multiple ways of doing something dynamically or where algorithms need to be selected at runtime based on varying conditions. By employing the Strategy pattern, you can achieve greater flexibility, maintainability, and reusability in your codebase, especially when dealing with algorithms or behaviors that may change or expand over time.