Giriş
Farklı algoritmalar veya iş kuralları, uygulama gereksinimlerine göre runtime anında seçilebiliyorsa, Strategy Pattern devreye girer. Örneğin; bir ödeme sisteminde kredi kartı, banka havalesi veya mobil ödeme stratejileri tek bir arayüzden yönetilir.
Bu yazıda:
- Davranış ailesi nasıl modellenir?
- Kurulum ve temel örnek
- Katmanlı mimaride kullanımı
- Karmaşık senaryolar & parametrik seçim
- Avantaj & Dezavantajlar

1. Strategy Pattern Nedir?
- Amacı: Bir davranış ailesi tanımlayıp, bunları birbirinin yerine kullanılır hale getirmek.
- Temel Bileşenler:
-
Context: Stratejiyi kullanan sınıf.
-
Strategy (Arayüz): Davranış tipini tanımlar.
-
ConcreteStrategy: Strategy arayüzünü uygulayan sınıflar.
-
2. Strategy Pattern kurulumu
A. Strategy Arayüzü
public interface IPaymentStrategy
{
void Pay(decimal amount);
}
B. ConcreteStrategy’ler
public class CreditCardPayment : IPaymentStrategy
{
public void Pay(decimal amount)
{
Console.WriteLine($"Kredi kartından {amount} TL ödendi.");
}
}
public class BankTransferPayment : IPaymentStrategy
{
public void Pay(decimal amount)
{
Console.WriteLine($"Havale ile {amount} TL ödendi.");
}
}
C. Context
public class PaymentProcessor
{
private readonly IPaymentStrategy _strategy;
public PaymentProcessor(IPaymentStrategy strategy)
{
_strategy =
strategy
?? throw new ArgumentNullException(nameof(strategy));
}
public void ProcessPayment(decimal amount)
{
if (amount <= 0)
throw new ArgumentOutOfRangeException(nameof(amount));
_strategy.Pay(amount);
}
}
D. Kullanım
var creditProcessor = new PaymentProcessor(new CreditCardPayment());
creditProcessor.ProcessPayment(100m);
var transferProcessor = new PaymentProcessor(new BankTransferPayment());
transferProcessor.ProcessPayment(200m);
3. Katmanlı Mimari Entegrasyonu
| Katman | Rol |
|---|---|
| Domain | İş kuralı strategy’leri; gerçek banka/payment gateway adaptörleri Infrastructure’da |
| Application | PaymentProcessor (Context) |
| API / UI | Controller / UI butonuyla strateji seçimi |

4. Strategy Pattern: seçim sınırları
A. Parametreye Göre Seçim
string userChoice = "CreditCard";
// Kullanım
var strategy = PaymentStrategyFactory.Create(userChoice);
new PaymentProcessor(strategy).ProcessPayment(150m);
public static class PaymentStrategyFactory
{
public static IPaymentStrategy Create(string type) =>
type switch
{
"CreditCard" => new CreditCardPayment(),
"BankTransfer" => new BankTransferPayment(),
_ => throw new ArgumentException("Bilinmeyen ödeme tipi."),
};
}
B. Dinamik Yükleme (Reflection)
string strategyName = "CreditCard";
decimal amount = 150m;
var allowedTypes = new Dictionary<string, Type>(StringComparer.Ordinal)
{
["CreditCard"] = typeof(CreditCardPayment),
["BankTransfer"] = typeof(BankTransferPayment),
};
if (!allowedTypes.TryGetValue(strategyName, out var type))
throw new ArgumentException(
"Bilinmeyen ödeme tipi.",
nameof(strategyName)
);
if (
Activator.CreateInstance(type)
is not IPaymentStrategy selectedStrategy
)
throw new InvalidOperationException("Strategy oluşturulamadı.");
new PaymentProcessor(selectedStrategy).ProcessPayment(amount);
5. Avantajlar & Dezavantajlar
Avantajlar
- Esneklik: Yeni strateji eklemek, Context’i değiştirmeyi gerektirmez.
- Tek Sorumluluk: Her strateji kendi sınıfında kapsüllenmiş.
- Test Edilebilirlik: Her strateji kolayca mock edilebilir.
Dezavantajlar
- Klasik Yük: Çok sayıda ConcreteStrategy sınıfı yönetimi zorlaşabilir.
- Ekstra Kod: Basit durumlarda gereksiz kompleksite.
İleri Okuma ve Kaynaklar
Sonuç
Strategy Pattern ile dinamik davranış seçimini soyutlayarak, uygulamanızın esnekliğini ve bakım kolaylığını artırabilirsiniz. Katmanlı yapılarda Context ve Strategy’leri doğru katmana yerleştirerek clean code prensiplerine uygun ilerleyin.
Ödeme sınıfları sadece console çıktısı üretir; gerçek transfer, authentication veya idempotency uygulamaz. Factory seçiminde case-sensitive allowlist kullanırız. Bilinmeyen string için fallback ödeme seçmeyin; istemcinin strategy tercihini yetkilendirme ve uygunluk kurallarıyla ayrıca doğrulayın.
Reflection kesiti dış girdiyi doğrudan Type.GetType ile çözmez; yalnız önceden seçilmiş iki tipe izin verir. Bu alternatif parametresiz constructor varsayar; dependency’ler varsa DI/factory kullanın. Native AOT/trim desteğini ayrıca doğrulayın. İki seçim kesiti ayrı alternatiftir, top-level kullanım satırları Program.cs başında yer alır.
Context mevcut contract içinde yeni strategy’yi kullanır; selection registry yine güncellenebilir. Strategy runtime’da değişmek zorunda değildir; constructor’da seçmek de geçerlidir. Bir contract’ın hata ve sonuç davranışını tüm strategy’ler korumalıdır. State Pattern ise nesnenin içsel durumuna bağlı geçişleri ele alır.
