Behavioral — Davranışsal Desenler

Strategy

Strateji Deseni

Amaç: Bir işi yapmanın farklı yollarını (algoritma ailesini) ayrı sınıflara taşıyıp çalışma zamanında birbirinin yerine kullanılabilir hale getirmek.

1

Basit Anlatım

Teknik terim yok — günlük hayattan bir benzetme

Evden havalimanına gitmeniz gerekiyor. Birkaç seçeneğiniz var: taksi (hızlı ama pahalı), otobüs (ucuz ama yavaş), bisiklet (bedava ama yorucu). Hedef aynı: havalimanına ulaşmak. Değişen tek şey nasıl gittiğiniz.

Seçiminizi o anki koşullara göre yaparsınız: acele varsa taksi, bütçe kısıtlıysa otobüs, hava güzelse bisiklet. Ve bu seçim size kalmıştır; yol size "sadece taksiyle gelebilirsin" demez.

Navigasyon uygulaması

Haritada rota oluştururken "araba", "yürüyüş" ve "toplu taşıma" seçenekleri vardır. Başlangıç ve bitiş noktası aynıdır, ama her seçenek rotayı farklı bir yöntemle hesaplar.

Strategy şunu der: "Bir işin birden fazla yapılış yolu varsa, her yolu ayrı bir parça yap; hangisini kullanacağına duruma göre karar ver."
2

Teknik Anlamı

Bir yazılımcının bakış açısıyla

Strategy, birbirinin yerine geçebilen algoritmaları ortak bir arayüzün arkasına koyar. Algoritmayı kullanan nesne (Context), somut stratejiyi bilmez; yalnızca arayüzü bilir. Strateji constructor üzerinden ya da çalışma zamanında değiştirilerek verilir.

Katılımcılar

Problem: koşul cehennemi

if (type == "standart") {...} else if (type == "hızlı") {...} else if .... Her yeni seçenek bu bloğu büyütür, sınıfı değiştirmeyi gerektirir ve test etmeyi zorlaştırır.

.NET'te Strategy

Avantajlar

Dezavantajlar

3

C# ile Uygulama

Adım adım, çalışan kod örneği

Senaryo: Bir alışveriş sepetinde kargo ücreti hesaplama. Standart, hızlı ve "belirli tutarın üstü ücretsiz" seçenekleri var.

Adım 1 Strategy arayüzü ve somut stratejiler

public interface IShippingStrategy
{
    string Name { get; }
    decimal Calculate(decimal cartTotal, double weightKg);
}

public class StandardShipping : IShippingStrategy
{
    public string Name => "Standart (3-5 gün)";
    public decimal Calculate(decimal total, double kg) => 30m + (decimal)kg * 5m;
}

public class ExpressShipping : IShippingStrategy
{
    public string Name => "Hızlı (ertesi gün)";
    public decimal Calculate(decimal total, double kg) => 75m + (decimal)kg * 10m;
}

public class FreeOverLimitShipping : IShippingStrategy
{
    private readonly decimal _limit;
    private readonly IShippingStrategy _fallback;

    public FreeOverLimitShipping(decimal limit, IShippingStrategy fallback)
    { _limit = limit; _fallback = fallback; }

    public string Name => $"{_limit} TL üstü ücretsiz";
    public decimal Calculate(decimal total, double kg) =>
        total >= _limit ? 0 : _fallback.Calculate(total, kg);
}

Adım 2 Context: stratejiyi kullanan sepet

Sepet hangi kargo yönteminin seçildiğini bilmez ve umursamaz; sadece Calculate çağırır.

public class ShoppingCart
{
    private readonly List<(string Name, decimal Price, double Kg)> _items = new();
    private IShippingStrategy _shipping = new StandardShipping();

    public void Add(string name, decimal price, double kg) => _items.Add((name, price, kg));

    public void SetShipping(IShippingStrategy strategy) => _shipping = strategy;

    public void Checkout()
    {
        decimal total = _items.Sum(i => i.Price);
        double weight = _items.Sum(i => i.Kg);
        decimal cargo = _shipping.Calculate(total, weight);
        Console.WriteLine($"  {_shipping.Name,-22} Ürünler: {total,7:0.00}  " +
                          $"Kargo: {cargo,6:0.00}  Toplam: {total + cargo,7:0.00} TL");
    }
}

Adım 3 Kullanım

Tüm parçaları bir araya getiren istemci (client) kodu:

var cart = new ShoppingCart();
cart.Add("Kitap", 180m, 0.5);
cart.Add("Kahve Makinesi", 950m, 3.0);

var options = new IShippingStrategy[]
{
    new StandardShipping(),
    new ExpressShipping(),
    new FreeOverLimitShipping(1000m, new StandardShipping()),
};

Console.WriteLine("Aynı sepet, farklı kargo stratejileri:");
foreach (var option in options)
{
    cart.SetShipping(option);    // stratejiyi çalışma zamanında değiştir
    cart.Checkout();
}

// Basit stratejiler için C#'ta lambda yeterlidir:
var names = new List<string> { "Zeynep", "Ali", "Mehmet" };
names.Sort((x, y) => x.Length.CompareTo(y.Length));   // sıralama stratejisi
Console.WriteLine($"\nUzunluğa göre sıralı: {string.Join(", ", names)}");

Konsol çıktısı

Aynı sepet, farklı kargo stratejileri:
  Standart (3-5 gün)     Ürünler: 1130,00  Kargo:  47,50  Toplam: 1177,50 TL
  Hızlı (ertesi gün)     Ürünler: 1130,00  Kargo: 110,00  Toplam: 1240,00 TL
  1000 TL üstü ücretsiz  Ürünler: 1130,00  Kargo:   0,00  Toplam: 1130,00 TL

Uzunluğa göre sıralı: Ali, Zeynep, Mehmet

Kodda dikkat edilmesi gerekenler

Özetle: Strategy, bir işin farklı yapılış yollarını değiştirilebilir parçalar haline getirir; böylece if/else zincirleri yerine esnek ve test edilebilir bir yapı oluşur.
← Ana sayfaya dön