Menu
Coddy logo textTech

Strategy Kalıbı

Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 55 / 70.

Strateji deseni (Strategy pattern), bir algoritma ailesi tanımlamanıza, her birini kendi sınıfında kapsüllemenize ve bunları çalışma zamanında birbirinin yerine kullanılabilir hale getirmenize olanak tanıyan davranışsal bir desendir. Davranışı doğrudan kodun içine yazmak (hardcoding) yerine, istediğiniz stratejiyi bir nesneye enjekte edersiniz.

Desen üç bölümden oluşur: algoritma sözleşmesini tanımlayan bir strateji arayüzü, farklı davranışları uygulayan somut strateji sınıfları ve bir strateji kullanan bir bağlam sınıfı:

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

Bağlam (ShoppingCart), hangi ödeme yöntemini kullandığını bilmez - sadece sağlanan strateji ne olursa olsun onun üzerindeki Pay() metodunu çağırır:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // Paid 99.99 via Credit Card

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // Paid 49.99 via PayPal

Strategy deseni karmaşık koşullu mantığı ortadan kaldırır. Yeni bir ödeme yöntemi eklemek, IPaymentStrategy arayüzünü uygulayan yeni bir sınıf oluşturmak anlamına gelir; ShoppingCart sınıfında herhangi bir değişiklik yapılmasına gerek kalmaz. Bu, kodunuzu genişletilmeye açık ancak değişikliğe kapalı hale getirir.

challenge icon

Görev

Kolay

Strateji (Strategy) desenini kullanarak bir nakliye maliyeti hesaplayıcı oluşturalım. Farklı nakliye yöntemlerinin farklı fiyatlandırma algoritmaları vardır ve sisteminiz, temel sipariş işleme mantığını değiştirmeden çalışma zamanında bunlar arasında geçiş yapılmasına izin vermelidir.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • ShippingStrategy.cs: Shipping ad alanı (namespace) içinde, double döndüren bir CalculateCost(double weight) metoduna sahip bir IShippingStrategy arayüzü (interface) tanımlayın. Ardından üç somut strateji sınıfı oluşturun:
    • StandardShipping - maliyeti weight * 1.5 olarak hesaplar
    • ExpressShipping - maliyeti weight * 3.0 + 5.0 olarak hesaplar (sabit bir ekspres ücreti içerir)
    • OvernightShipping - maliyeti weight * 5.0 + 10.0 olarak hesaplar (daha yüksek taban ücretli premium hizmet)
  • OrderProcessor.cs: Aynı ad alanında bir OrderProcessor sınıfı oluşturun. Bu, bir nakliye stratejisi kullanan bağlam (context) sınıfınızdır. Şunlara sahip olmalıdır:
    • Mevcut IShippingStrategy nesnesini tutmak için özel (private) bir alan
    • Nakliye stratejisini değiştirmek için bir SetShippingMethod(IShippingStrategy strategy) metodu
    • Nakliye maliyetini hesaplamak ve döndürmek için mevcut stratejiyi kullanan bir ProcessOrder(double weight) metodu
  • Program.cs: Bir OrderProcessor oluşturarak ve nakliye stratejilerini çalışma zamanında nasıl değiştirebileceğinizi göstererek her şeyi bir araya getirin. Aynı işlemci, sadece stratejisini değiştirerek farklı algoritmalar kullanarak maliyetleri hesaplayabilir.

İki girdi alacaksınız:

  • Nakliye yöntemi türü: standard, express veya overnight
  • Ondalık sayı olarak paket ağırlığı (örneğin, 4.5)

Bir OrderProcessor oluşturun, girdi türüne göre uygun nakliye stratejisini ayarlayın, ardından siparişi işleyin ve hesaplanan maliyeti yazdırın.

Örneğin, girdiler express ve 4.5 ise, çıktı şöyle olmalıdır:

18.5

Bu, Strateji deseninin gücünü gösterir - OrderProcessor sınıfınızın kendisi herhangi bir nakliye hesaplama mantığı içermez. Sadece kendisine verilen stratejiye yetki devreder (delegate), bu da işlemciyi hiç değiştirmeden yeni nakliye yöntemleri (örneğin DroneDelivery) eklemeyi kolaylaştırır!

Kopya kağıdı

Strateji deseni (Strategy pattern), bir algoritma ailesi tanımlayan, her birini kendi sınıfına kapsülleyen ve bunları çalışma zamanında birbirinin yerine kullanılabilir hale getiren davranışsal bir desendir.

Desen üç bölümden oluşur:

  • Strateji arayüzü (Strategy interface): algoritma sözleşmesini tanımlar
  • Somut strateji sınıfları (Concrete strategy classes): farklı davranışları uygular
  • Bağlam sınıfı (Context class): uygulama detaylarını bilmeden bir stratejiyi kullanır

Örnek yapı:

// Strateji arayüzü
public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

// Somut stratejiler
public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

// Bağlam sınıfı
public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

Kullanım - çalışma zamanında stratejileri değiştirme:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // Paid 99.99 via Credit Card

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // Paid 49.99 via PayPal

Faydaları:

  • Karmaşık koşullu mantığı ortadan kaldırır
  • Gelişime açık, değişime kapalıdır
  • Yeni stratejiler eklemek sadece yeni sınıflar oluşturmayı gerektirir, mevcut kodda değişiklik yapılmaz

Kendin dene

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // Girdiyi oku
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: Bir OrderProcessor örneği oluşturun

        // TODO: shippingType değerine göre ("standard", "express" veya "overnight"),
        // uygun gönderim stratejisini oluşturun ve işlemci üzerinde ayarlayın

        // TODO: Siparişi işleyin ve hesaplanan maliyeti yazdırın
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler